2000-05-01 13:42:38 +04:00
/**********************************************************************
1998-01-16 15:13:05 +03:00
process . c -
$ Author $
created at : Tue Aug 10 14 : 30 : 50 JST 1993
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
Copyright ( C ) 1993 - 2007 Yukihiro Matsumoto
2000-05-01 13:42:38 +04:00
Copyright ( C ) 2000 Network Applied Communication Laboratory , Inc .
2000-05-09 08:53:16 +04:00
Copyright ( C ) 2000 Information - technology Promotion Agency , Japan
1998-01-16 15:13:05 +03:00
2000-05-01 13:42:38 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-01-16 15:13:05 +03:00
2020-05-08 12:31:09 +03:00
# include "ruby/internal/config.h"
2007-02-05 15:21:01 +03:00
2021-02-09 09:39:56 +03:00
# include "ruby/fiber/scheduler.h"
2020-08-20 04:51:45 +03:00
2019-12-04 11:16:30 +03:00
# include <ctype.h>
1998-01-16 15:13:05 +03:00
# include <errno.h>
# include <signal.h>
2019-12-04 11:16:30 +03:00
# include <stdarg.h>
# include <stdio.h>
# include <time.h>
2003-10-13 17:05:24 +04:00
# ifdef HAVE_STDLIB_H
2019-12-04 11:16:30 +03:00
# include <stdlib.h>
2003-10-13 17:05:24 +04:00
# endif
2019-12-04 11:16:30 +03:00
1998-01-16 15:13:05 +03:00
# ifdef HAVE_UNISTD_H
2019-12-04 11:16:30 +03:00
# include <unistd.h>
1998-01-16 15:13:05 +03:00
# endif
2019-12-04 11:16:30 +03:00
2004-02-16 09:45:32 +03:00
# ifdef HAVE_FCNTL_H
2019-12-04 11:16:30 +03:00
# include <fcntl.h>
2004-02-16 09:45:32 +03:00
# endif
2019-12-04 11:16:30 +03:00
2011-08-19 09:25:52 +04:00
# ifdef HAVE_PROCESS_H
2019-12-04 11:16:30 +03:00
# include <process.h>
2011-08-19 09:25:52 +04:00
# endif
2002-02-06 10:30:13 +03:00
2003-11-27 18:34:53 +03:00
# ifndef EXIT_SUCCESS
2019-12-04 11:16:30 +03:00
# define EXIT_SUCCESS 0
2003-11-27 18:34:53 +03:00
# endif
2019-12-04 11:16:30 +03:00
2003-10-13 17:05:24 +04:00
# ifndef EXIT_FAILURE
2019-12-04 11:16:30 +03:00
# define EXIT_FAILURE 1
2003-10-13 17:05:24 +04:00
# endif
1998-01-16 15:13:05 +03:00
# ifdef HAVE_SYS_WAIT_H
# include <sys / wait.h>
# endif
2019-12-04 11:16:30 +03:00
2004-11-14 13:06:16 +03:00
# ifdef HAVE_SYS_RESOURCE_H
1998-01-16 15:13:05 +03:00
# include <sys / resource.h>
# endif
2019-12-04 11:16:30 +03:00
2014-09-03 07:06:17 +04:00
# ifdef HAVE_VFORK_H
# include <vfork.h>
# endif
2019-12-04 11:16:30 +03:00
2008-05-08 01:43:54 +04:00
# ifdef HAVE_SYS_PARAM_H
# include <sys / param.h>
# endif
2019-12-04 11:16:30 +03:00
2008-05-08 01:43:54 +04:00
# ifndef MAXPATHLEN
# define MAXPATHLEN 1024
# endif
1998-01-16 15:13:05 +03:00
2008-04-24 19:16:38 +04:00
# include <sys/stat.h>
2012-05-17 06:48:59 +04:00
2013-08-11 06:59:30 +04:00
# ifdef HAVE_SYS_TIME_H
2019-12-04 11:16:30 +03:00
# include <sys / time.h>
2013-08-11 06:59:30 +04:00
# endif
2019-12-04 11:16:30 +03:00
2001-02-16 10:53:21 +03:00
# ifdef HAVE_SYS_TIMES_H
2019-12-04 11:16:30 +03:00
# include <sys / times.h>
2001-02-16 10:53:21 +03:00
# endif
2012-03-28 11:40:02 +04:00
# ifdef HAVE_PWD_H
2019-12-04 11:16:30 +03:00
# include <pwd.h>
2012-03-28 11:40:02 +04:00
# endif
2019-12-04 11:16:30 +03:00
2003-06-09 14:02:36 +04:00
# ifdef HAVE_GRP_H
2019-12-04 11:16:30 +03:00
# include <grp.h>
2015-04-14 05:25:02 +03:00
# ifdef __CYGWIN__
int initgroups ( const char * , rb_gid_t ) ;
# endif
2003-06-09 08:27:17 +04:00
# endif
2019-12-04 11:16:30 +03:00
2014-09-05 07:43:28 +04:00
# ifdef HAVE_SYS_ID_H
2019-12-04 11:16:30 +03:00
# include <sys / id.h>
2014-09-05 07:43:28 +04:00
# endif
2003-06-07 19:34:31 +04:00
2013-08-15 21:18:45 +04:00
# ifdef __APPLE__
# include <mach / mach_time.h>
# endif
2019-12-04 11:16:30 +03:00
# include "dln.h"
# include "hrtime.h"
# include "internal.h"
# include "internal/bits.h"
2020-02-12 05:53:51 +03:00
# include "internal/dir.h"
2019-12-04 11:16:30 +03:00
# include "internal/error.h"
# include "internal/eval.h"
# include "internal/hash.h"
2021-10-25 14:47:19 +03:00
# include "internal/numeric.h"
2019-12-04 11:16:30 +03:00
# include "internal/object.h"
# include "internal/process.h"
# include "internal/thread.h"
# include "internal/variable.h"
# include "internal/warnings.h"
2020-11-23 07:28:08 +03:00
# include "mjit.h"
2019-12-04 11:16:30 +03:00
# include "ruby/io.h"
# include "ruby/st.h"
# include "ruby/thread.h"
# include "ruby/util.h"
# include "vm_core.h"
2020-11-17 10:40:47 +03:00
# include "ruby/ractor.h"
2019-12-04 11:16:30 +03:00
2014-06-16 09:35:59 +04:00
/* define system APIs */
# ifdef _WIN32
# undef open
# define open rb_w32_uopen
# endif
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
# if defined(HAVE_TIMES) || defined(_WIN32)
2008-04-26 12:31:13 +04:00
static VALUE rb_cProcessTms ;
2001-02-16 10:53:21 +03:00
# endif
2001-02-20 17:52:31 +03:00
# ifndef WIFEXITED
# define WIFEXITED(w) (((w) & 0xff) == 0)
# endif
# ifndef WIFSIGNALED
# define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
# endif
# ifndef WIFSTOPPED
# define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
# endif
# ifndef WEXITSTATUS
# define WEXITSTATUS(w) (((w) >> 8) & 0xff)
# endif
# ifndef WTERMSIG
# define WTERMSIG(w) ((w) & 0x7f)
# endif
# ifndef WSTOPSIG
# define WSTOPSIG WEXITSTATUS
# endif
2003-07-23 06:39:46 +04:00
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
# define HAVE_44BSD_SETUID 1
# define HAVE_44BSD_SETGID 1
# endif
2004-10-31 17:37:08 +03:00
# ifdef __NetBSD__
# undef HAVE_SETRUID
# undef HAVE_SETRGID
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
# ifdef BROKEN_SETREUID
# define setreuid ruby_setreuid
2012-04-03 13:33:40 +04:00
int setreuid ( rb_uid_t ruid , rb_uid_t euid ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
# endif
# ifdef BROKEN_SETREGID
# define setregid ruby_setregid
2012-04-03 13:33:40 +04:00
int setregid ( rb_gid_t rgid , rb_gid_t egid ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
# endif
2012-07-09 19:52:49 +04:00
# if defined(HAVE_44BSD_SETUID) || defined(__APPLE__)
2003-07-23 06:39:46 +04:00
# if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
# define OBSOLETE_SETREUID 1
# endif
# if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
# define OBSOLETE_SETREGID 1
# endif
# endif
2012-10-09 12:13:29 +04:00
static void check_uid_switch ( void ) ;
static void check_gid_switch ( void ) ;
2017-11-14 07:42:38 +03:00
static int exec_async_signal_safe ( const struct rb_execarg * , char * , size_t ) ;
2012-10-09 12:13:29 +04:00
2021-09-13 21:59:04 +03:00
VALUE rb_envtbl ( void ) ;
VALUE rb_env_to_hash ( void ) ;
2012-10-09 12:13:29 +04:00
# if 1
# define p_uid_from_name p_uid_from_name
# define p_gid_from_name p_gid_from_name
# endif
2020-04-15 14:29:16 +03:00
# if defined(HAVE_UNISTD_H)
# if defined(HAVE_GETLOGIN_R)
# define USE_GETLOGIN_R 1
# define GETLOGIN_R_SIZE_DEFAULT 0x100
# define GETLOGIN_R_SIZE_LIMIT 0x1000
# if defined(_SC_LOGIN_NAME_MAX)
# define GETLOGIN_R_SIZE_INIT sysconf(_SC_LOGIN_NAME_MAX)
# else
# define GETLOGIN_R_SIZE_INIT GETLOGIN_R_SIZE_DEFAULT
# endif
# elif defined(HAVE_GETLOGIN)
# define USE_GETLOGIN 1
# endif
# endif
2012-10-09 12:13:29 +04:00
# if defined(HAVE_PWD_H)
2020-04-15 14:29:16 +03:00
# if defined(HAVE_GETPWUID_R)
# define USE_GETPWUID_R 1
# elif defined(HAVE_GETPWUID)
# define USE_GETPWUID 1
# endif
# if defined(HAVE_GETPWNAM_R)
2013-02-07 19:07:35 +04:00
# define USE_GETPWNAM_R 1
2020-04-15 14:29:16 +03:00
# elif defined(HAVE_GETPWNAM)
# define USE_GETPWNAM 1
# endif
# if defined(HAVE_GETPWNAM_R) || defined(HAVE_GETPWUID_R)
2014-03-08 08:08:46 +04:00
# define GETPW_R_SIZE_DEFAULT 0x1000
2014-03-08 08:30:56 +04:00
# define GETPW_R_SIZE_LIMIT 0x10000
2020-04-15 14:29:16 +03:00
# if defined(_SC_GETPW_R_SIZE_MAX)
# define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX)
# else
# define GETPW_R_SIZE_INIT GETPW_R_SIZE_DEFAULT
# endif
2013-02-07 19:07:35 +04:00
# endif
# ifdef USE_GETPWNAM_R
2012-10-09 12:13:29 +04:00
# define PREPARE_GETPWNAM \
2014-03-08 07:55:01 +04:00
VALUE getpw_buf = 0
# define FINISH_GETPWNAM \
2017-05-11 02:18:07 +03:00
( getpw_buf ? ( void ) rb_str_resize ( getpw_buf , 0 ) : ( void ) 0 )
2014-03-08 07:55:01 +04:00
# define OBJ2UID1(id) obj2uid((id), &getpw_buf)
# define OBJ2UID(id) obj2uid0(id)
static rb_uid_t obj2uid ( VALUE id , VALUE * getpw_buf ) ;
static inline rb_uid_t
obj2uid0 ( VALUE id )
{
rb_uid_t uid ;
PREPARE_GETPWNAM ;
uid = OBJ2UID1 ( id ) ;
FINISH_GETPWNAM ;
return uid ;
}
2012-10-09 12:13:29 +04:00
# else
# define PREPARE_GETPWNAM /* do nothing */
2014-03-08 07:55:01 +04:00
# define FINISH_GETPWNAM /* do nothing */
2014-04-09 16:05:14 +04:00
# define OBJ2UID1(id) obj2uid((id))
2012-10-09 12:13:29 +04:00
# define OBJ2UID(id) obj2uid((id))
static rb_uid_t obj2uid ( VALUE id ) ;
# endif
# else
# define PREPARE_GETPWNAM /* do nothing */
2014-03-08 07:55:01 +04:00
# define FINISH_GETPWNAM /* do nothing */
2014-04-09 16:05:14 +04:00
# define OBJ2UID1(id) NUM2UIDT(id)
2012-10-09 12:13:29 +04:00
# define OBJ2UID(id) NUM2UIDT(id)
# ifdef p_uid_from_name
# undef p_uid_from_name
# define p_uid_from_name rb_f_notimplement
# endif
# endif
# if defined(HAVE_GRP_H)
2013-02-07 19:07:35 +04:00
# if defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
# define USE_GETGRNAM_R
2014-03-08 08:08:46 +04:00
# define GETGR_R_SIZE_INIT sysconf(_SC_GETGR_R_SIZE_MAX)
# define GETGR_R_SIZE_DEFAULT 0x1000
2014-03-08 08:30:56 +04:00
# define GETGR_R_SIZE_LIMIT 0x10000
2013-02-07 19:07:35 +04:00
# endif
# ifdef USE_GETGRNAM_R
2012-10-09 12:13:29 +04:00
# define PREPARE_GETGRNAM \
2014-03-08 07:55:01 +04:00
VALUE getgr_buf = 0
# define FINISH_GETGRNAM \
2017-05-11 02:18:07 +03:00
( getgr_buf ? ( void ) rb_str_resize ( getgr_buf , 0 ) : ( void ) 0 )
2014-03-08 07:55:01 +04:00
# define OBJ2GID1(id) obj2gid((id), &getgr_buf)
# define OBJ2GID(id) obj2gid0(id)
static rb_gid_t obj2gid ( VALUE id , VALUE * getgr_buf ) ;
static inline rb_gid_t
obj2gid0 ( VALUE id )
{
rb_gid_t gid ;
PREPARE_GETGRNAM ;
gid = OBJ2GID1 ( id ) ;
FINISH_GETGRNAM ;
return gid ;
}
static rb_gid_t obj2gid ( VALUE id , VALUE * getgr_buf ) ;
2012-10-09 12:13:29 +04:00
# else
# define PREPARE_GETGRNAM /* do nothing */
2014-03-08 07:55:01 +04:00
# define FINISH_GETGRNAM /* do nothing */
2014-04-09 16:05:14 +04:00
# define OBJ2GID1(id) obj2gid((id))
2012-10-09 12:13:29 +04:00
# define OBJ2GID(id) obj2gid((id))
static rb_gid_t obj2gid ( VALUE id ) ;
# endif
# else
# define PREPARE_GETGRNAM /* do nothing */
2014-03-08 07:55:01 +04:00
# define FINISH_GETGRNAM /* do nothing */
2014-04-09 16:05:14 +04:00
# define OBJ2GID1(id) NUM2GIDT(id)
2012-10-09 12:13:29 +04:00
# define OBJ2GID(id) NUM2GIDT(id)
# ifdef p_gid_from_name
# undef p_gid_from_name
# define p_gid_from_name rb_f_notimplement
# endif
# endif
2004-01-02 09:01:12 +03:00
2013-08-22 15:19:49 +04:00
# if SIZEOF_CLOCK_T == SIZEOF_INT
typedef unsigned int unsigned_clock_t ;
# elif SIZEOF_CLOCK_T == SIZEOF_LONG
typedef unsigned long unsigned_clock_t ;
# elif defined(HAVE_LONG_LONG) && SIZEOF_CLOCK_T == SIZEOF_LONG_LONG
typedef unsigned LONG_LONG unsigned_clock_t ;
# endif
2016-07-04 10:05:00 +03:00
# ifndef HAVE_SIG_T
2016-07-04 07:57:27 +03:00
typedef void ( * sig_t ) ( int ) ;
# endif
2013-08-22 15:19:49 +04:00
2018-12-22 13:23:06 +03:00
# define id_exception idException
static ID id_in , id_out , id_err , id_pid , id_uid , id_gid ;
2015-02-23 10:05:30 +03:00
static ID id_close , id_child ;
2014-11-24 06:44:24 +03:00
# ifdef HAVE_SETPGID
static ID id_pgroup ;
# endif
# ifdef _WIN32
static ID id_new_pgroup ;
# endif
2021-09-13 21:59:04 +03:00
static ID id_unsetenv_others , id_chdir , id_umask , id_close_others ;
2014-11-24 06:44:24 +03:00
static ID id_nanosecond , id_microsecond , id_millisecond , id_second ;
static ID id_float_microsecond , id_float_millisecond , id_float_second ;
static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME , id_TIME_BASED_CLOCK_REALTIME ;
2022-02-18 11:59:15 +03:00
# ifdef CLOCK_REALTIME
static ID id_CLOCK_REALTIME ;
# define RUBY_CLOCK_REALTIME ID2SYM(id_CLOCK_REALTIME)
# endif
# ifdef CLOCK_MONOTONIC
static ID id_CLOCK_MONOTONIC ;
# define RUBY_CLOCK_MONOTONIC ID2SYM(id_CLOCK_MONOTONIC)
# endif
# ifdef CLOCK_PROCESS_CPUTIME_ID
static ID id_CLOCK_PROCESS_CPUTIME_ID ;
# define RUBY_CLOCK_PROCESS_CPUTIME_ID ID2SYM(id_CLOCK_PROCESS_CPUTIME_ID)
# endif
# ifdef CLOCK_THREAD_CPUTIME_ID
static ID id_CLOCK_THREAD_CPUTIME_ID ;
# define RUBY_CLOCK_THREAD_CPUTIME_ID ID2SYM(id_CLOCK_THREAD_CPUTIME_ID)
# endif
2014-11-24 06:44:24 +03:00
# ifdef HAVE_TIMES
static ID id_TIMES_BASED_CLOCK_MONOTONIC ;
static ID id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID ;
# endif
# ifdef RUSAGE_SELF
static ID id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID ;
# endif
static ID id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID ;
# ifdef __APPLE__
static ID id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ;
2022-02-18 11:59:15 +03:00
# define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
2014-11-24 06:44:24 +03:00
# endif
static ID id_hertz ;
2015-06-19 20:49:27 +03:00
/* execv and execl are async-signal-safe since SUSv4 (POSIX.1-2008, XPG7) */
# if defined(__sun) && !defined(_XPG7) /* Solaris 10, 9, ... */
# define execv(path, argv) (rb_async_bug_errno("unreachable: async-signal-unsafe execv() is called", 0))
# define execl(path, arg0, arg1, arg2, term) do { extern char **environ; execle((path), (arg0), (arg1), (arg2), (term), (environ)); } while (0)
# define ALWAYS_NEED_ENVP 1
# else
# define ALWAYS_NEED_ENVP 0
# endif
2018-07-13 02:23:25 +03:00
static void
assert_close_on_exec ( int fd )
{
# if VM_CHECK_MODE > 0
# if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(FD_CLOEXEC)
2018-07-15 12:57:27 +03:00
int flags = fcntl ( fd , F_GETFD ) ;
if ( flags = = - 1 ) {
static const char m [ ] = " reserved FD closed unexpectedly? \n " ;
2018-07-24 12:15:58 +03:00
( void ) ! write ( 2 , m , sizeof ( m ) - 1 ) ;
2018-07-15 12:57:27 +03:00
return ;
}
if ( flags & FD_CLOEXEC ) return ;
rb_bug ( " reserved FD did not have close-on-exec set " ) ;
2018-07-13 02:23:25 +03:00
# else
2018-07-15 12:57:27 +03:00
rb_bug ( " reserved FD without close-on-exec support " ) ;
2018-07-13 02:23:25 +03:00
# endif /* FD_CLOEXEC */
# endif /* VM_CHECK_MODE */
}
2015-07-16 05:39:30 +03:00
static inline int
close_unless_reserved ( int fd )
2015-07-15 17:26:22 +03:00
{
if ( rb_reserved_fd_p ( fd ) ) { /* async-signal-safe */
2018-07-13 02:23:25 +03:00
assert_close_on_exec ( fd ) ;
2015-07-15 17:26:22 +03:00
return 0 ;
}
return close ( fd ) ; /* async-signal-safe */
}
2015-04-09 17:23:42 +03:00
/*#define DEBUG_REDIRECT*/
# if defined(DEBUG_REDIRECT)
static void
ttyprintf ( const char * fmt , . . . )
{
va_list ap ;
FILE * tty ;
int save = errno ;
# ifdef _WIN32
tty = fopen ( " con " , " w " ) ;
# else
tty = fopen ( " /dev/tty " , " w " ) ;
# endif
if ( ! tty )
return ;
va_start ( ap , fmt ) ;
vfprintf ( tty , fmt , ap ) ;
va_end ( ap ) ;
fclose ( tty ) ;
errno = save ;
}
static int
redirect_dup ( int oldfd )
{
int ret ;
ret = dup ( oldfd ) ;
ttyprintf ( " dup(%d) => %d \n " , oldfd , ret ) ;
return ret ;
}
static int
redirect_dup2 ( int oldfd , int newfd )
{
int ret ;
2015-08-14 12:44:10 +03:00
ret = dup2 ( oldfd , newfd ) ;
2015-04-09 19:33:02 +03:00
ttyprintf ( " dup2(%d, %d) => %d \n " , oldfd , newfd , ret ) ;
2015-04-09 17:23:42 +03:00
return ret ;
}
2015-09-12 08:30:05 +03:00
static int
redirect_cloexec_dup ( int oldfd )
{
int ret ;
ret = rb_cloexec_dup ( oldfd ) ;
ttyprintf ( " cloexec_dup(%d) => %d \n " , oldfd , ret ) ;
return ret ;
}
static int
redirect_cloexec_dup2 ( int oldfd , int newfd )
{
int ret ;
ret = rb_cloexec_dup2 ( oldfd , newfd ) ;
ttyprintf ( " cloexec_dup2(%d, %d) => %d \n " , oldfd , newfd , ret ) ;
return ret ;
}
2015-04-09 17:23:42 +03:00
static int
redirect_close ( int fd )
{
int ret ;
2015-07-15 17:26:22 +03:00
ret = close_unless_reserved ( fd ) ;
2015-04-09 19:33:02 +03:00
ttyprintf ( " close(%d) => %d \n " , fd , ret ) ;
return ret ;
}
static int
parent_redirect_open ( const char * pathname , int flags , mode_t perm )
{
int ret ;
ret = rb_cloexec_open ( pathname , flags , perm ) ;
ttyprintf ( " parent_open( \" %s \" , 0x%x, 0%o) => %d \n " , pathname , flags , perm , ret ) ;
return ret ;
}
static int
parent_redirect_close ( int fd )
{
int ret ;
2015-07-15 17:26:22 +03:00
ret = close_unless_reserved ( fd ) ;
2015-04-09 19:33:02 +03:00
ttyprintf ( " parent_close(%d) => %d \n " , fd , ret ) ;
2015-04-09 17:23:42 +03:00
return ret ;
}
# else
# define redirect_dup(oldfd) dup(oldfd)
2015-08-14 12:44:10 +03:00
# define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
2015-09-12 08:30:05 +03:00
# define redirect_cloexec_dup(oldfd) rb_cloexec_dup(oldfd)
# define redirect_cloexec_dup2(oldfd, newfd) rb_cloexec_dup2((oldfd), (newfd))
2015-07-15 17:26:22 +03:00
# define redirect_close(fd) close_unless_reserved(fd)
2015-04-09 19:33:02 +03:00
# define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm))
2015-07-15 17:26:22 +03:00
# define parent_redirect_close(fd) close_unless_reserved(fd)
2015-04-09 17:23:42 +03:00
# endif
2018-02-23 05:18:52 +03:00
/*
* Document - module : Process
*
2019-10-24 19:35:36 +03:00
* The module contains several groups of functionality for handling OS processes :
*
2019-12-24 15:01:47 +03:00
* * Low - level property introspection and management of the current process , like
2019-10-24 19:35:36 +03:00
* Process . argv0 , Process . pid ;
* * Low - level introspection of other processes , like Process . getpgid , Process . getpriority ;
2019-12-24 15:01:47 +03:00
* * Management of the current process : Process . abort , Process . exit , Process . daemon , etc .
* ( for convenience , most of those are also available as global functions
2019-10-24 19:35:36 +03:00
* and module functions of Kernel ) ;
2019-12-24 15:01:47 +03:00
* * Creation and management of child processes : Process . fork , Process . spawn , and
2019-10-24 19:35:36 +03:00
* related methods ;
* * Management of low - level system clock : Process . times and Process . clock_gettime ,
* which could be important for proper benchmarking and other elapsed
* time measurement tasks .
2018-02-23 05:18:52 +03:00
*/
2019-08-29 04:23:14 +03:00
static VALUE
get_pid ( void )
{
return PIDT2NUM ( getpid ( ) ) ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . pid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the process id of this process . Not available on all
* platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . pid # = > 27415
*/
1998-01-16 15:13:05 +03:00
static VALUE
2019-08-29 04:23:14 +03:00
proc_get_pid ( VALUE _ )
1998-01-16 15:13:05 +03:00
{
2019-08-29 04:23:14 +03:00
return get_pid ( ) ;
1998-01-16 15:13:05 +03:00
}
2019-08-28 11:48:48 +03:00
static VALUE
2019-08-29 04:23:14 +03:00
get_ppid ( void )
2019-08-28 11:48:48 +03:00
{
2019-08-29 04:23:14 +03:00
return PIDT2NUM ( getppid ( ) ) ;
2019-08-28 11:48:48 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . ppid - > integer
2004-06-29 05:17:39 +04:00
*
2008-09-08 13:17:22 +04:00
* Returns the process id of the parent of this process . Returns
* untrustworthy value on Win32 / 64. Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* puts " I am #{Process.pid} "
* Process . fork { puts " Dad is #{Process.ppid} " }
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* < em > produces : < / em >
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* I am 27417
* Dad is 27417
*/
2019-08-28 11:48:48 +03:00
static VALUE
proc_get_ppid ( VALUE _ )
{
return get_ppid ( ) ;
}
2004-01-02 09:01:12 +03:00
/*********************************************************************
*
* Document - class : Process : : Status
*
2019-03-28 06:33:35 +03:00
* Process : : Status encapsulates the information on the
2004-01-02 09:01:12 +03:00
* status of a running or terminated system process . The built - in
* variable < code > $ ? < / code > is either + nil + or a
2019-03-28 06:33:35 +03:00
* Process : : Status object .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { exit 99 } # = > 26557
* Process . wait # = > 26557
* $ ? . class # = > Process : : Status
* $ ? . to_i # = > 25344
* $ ? > > 8 # = > 99
* $ ? . stopped ? # = > false
* $ ? . exited ? # = > true
* $ ? . exitstatus # = > 99
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Posix systems record information on processes using a 16 - bit
* integer . The lower bits record the process status ( stopped ,
* exited , signaled ) and the upper bits possibly contain additional
* information ( for example the program ' s return code in the case of
* exited processes ) . Pre Ruby 1.8 , these bits were exposed directly
* to the Ruby program . Ruby now encapsulates these in a
2019-03-28 06:33:35 +03:00
* Process : : Status object . To maximize compatibility ,
2004-01-02 09:01:12 +03:00
* however , these objects retain a bit - oriented interface . In the
* descriptions that follow , when we talk about the integer value of
* _stat_ , we ' re referring to this 16 bit value .
*/
2008-04-26 12:31:13 +04:00
static VALUE rb_cProcessStatus ;
1998-01-16 15:13:05 +03:00
2020-12-07 23:29:09 +03:00
struct rb_process_status {
rb_pid_t pid ;
int status ;
2020-12-24 10:44:38 +03:00
int error ;
2020-12-07 23:29:09 +03:00
} ;
static const rb_data_type_t rb_process_status_type = {
. wrap_struct_name = " Process::Status " ,
. function = {
. dfree = RUBY_DEFAULT_FREE ,
} ,
. data = NULL ,
. flags = RUBY_TYPED_FREE_IMMEDIATELY ,
} ;
2020-12-09 05:49:20 +03:00
static VALUE
rb_process_status_allocate ( VALUE klass )
{
2020-12-07 23:29:09 +03:00
struct rb_process_status * data = NULL ;
return TypedData_Make_Struct ( klass , struct rb_process_status , & rb_process_status_type , data ) ;
}
2007-02-08 09:48:34 +03:00
VALUE
rb_last_status_get ( void )
{
2008-07-10 07:10:00 +04:00
return GET_THREAD ( ) - > last_status ;
2007-02-08 09:48:34 +03:00
}
2017-12-12 12:00:17 +03:00
/*
* call - seq :
2017-12-12 18:01:02 +03:00
* Process . last_status - > Process : : Status or nil
2017-12-12 12:00:17 +03:00
*
2017-12-14 13:24:38 +03:00
* Returns the status of the last executed child process in the
2017-12-12 12:00:17 +03:00
* current thread .
*
* Process . wait Process . spawn ( " ruby " , " -e " , " exit 13 " )
* Process . last_status # = > # < Process : : Status : pid 4825 exit 13 >
*
2017-12-14 13:24:38 +03:00
* If no child process has ever been executed in the current
2017-12-12 12:00:17 +03:00
* thread , this returns + nil + .
*
* Process . last_status # = > nil
*/
static VALUE
proc_s_last_status ( VALUE mod )
{
2017-12-13 13:16:05 +03:00
return rb_last_status_get ( ) ;
2017-12-12 12:00:17 +03:00
}
2020-12-09 05:49:20 +03:00
VALUE
2020-12-24 10:44:38 +03:00
rb_process_status_new ( rb_pid_t pid , int status , int error )
2001-02-15 09:01:00 +03:00
{
2020-12-07 23:29:09 +03:00
VALUE last_status = rb_process_status_allocate ( rb_cProcessStatus ) ;
struct rb_process_status * data = RTYPEDDATA_DATA ( last_status ) ;
data - > pid = pid ;
data - > status = status ;
2020-12-24 10:44:38 +03:00
data - > error = error ;
2020-12-07 23:29:09 +03:00
rb_obj_freeze ( last_status ) ;
2020-12-09 05:49:20 +03:00
return last_status ;
}
2020-12-16 06:31:40 +03:00
static VALUE
process_status_dump ( VALUE status )
{
VALUE dump = rb_class_new_instance ( 0 , 0 , rb_cObject ) ;
struct rb_process_status * data = RTYPEDDATA_DATA ( status ) ;
if ( data - > pid ) {
rb_ivar_set ( dump , id_status , INT2NUM ( data - > status ) ) ;
rb_ivar_set ( dump , id_pid , PIDT2NUM ( data - > pid ) ) ;
}
return dump ;
}
static VALUE
process_status_load ( VALUE real_obj , VALUE load_obj )
{
struct rb_process_status * data = rb_check_typeddata ( real_obj , & rb_process_status_type ) ;
VALUE status = rb_attr_get ( load_obj , id_status ) ;
VALUE pid = rb_attr_get ( load_obj , id_pid ) ;
data - > pid = NIL_P ( pid ) ? 0 : NUM2PIDT ( pid ) ;
data - > status = NIL_P ( status ) ? 0 : NUM2INT ( status ) ;
return real_obj ;
}
2020-12-09 05:49:20 +03:00
void
rb_last_status_set ( int status , rb_pid_t pid )
{
2020-12-24 10:44:38 +03:00
GET_THREAD ( ) - > last_status = rb_process_status_new ( pid , status , 0 ) ;
2001-02-15 09:01:00 +03:00
}
2012-08-29 18:44:08 +04:00
void
2007-02-08 09:48:34 +03:00
rb_last_status_clear ( void )
2007-02-05 15:21:01 +03:00
{
2008-07-10 07:10:00 +04:00
GET_THREAD ( ) - > last_status = Qnil ;
2007-02-05 15:21:01 +03:00
}
2004-01-02 09:01:12 +03:00
2020-12-24 13:47:35 +03:00
static rb_pid_t
pst_pid ( VALUE pst )
{
struct rb_process_status * data = RTYPEDDATA_DATA ( pst ) ;
return data - > pid ;
}
static int
pst_status ( VALUE pst )
{
struct rb_process_status * data = RTYPEDDATA_DATA ( pst ) ;
return data - > status ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat . to_i - > integer
2004-06-29 05:17:39 +04:00
*
2020-12-20 18:40:56 +03:00
* Returns the bits in _stat_ as an Integer . Poking
2004-01-02 09:01:12 +03:00
* around in these bits is platform dependent .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { exit 0xab } # = > 26566
* Process . wait # = > 26566
* sprintf ( ' % 04 x ' , $ ? . to_i ) # = > " ab00 "
*/
2001-02-15 09:01:00 +03:00
static VALUE
2020-12-07 23:29:09 +03:00
pst_to_i ( VALUE self )
2001-02-15 09:01:00 +03:00
{
2020-12-24 13:47:35 +03:00
int status = pst_status ( self ) ;
return RB_INT2NUM ( status ) ;
2001-02-15 09:01:00 +03:00
}
2020-12-24 13:47:35 +03:00
# define PST2INT(st) pst_status(st)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat . pid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the process ID that this status object represents .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { exit } # = > 26569
* Process . wait # = > 26569
* $ ? . pid # = > 26569
*/
2002-12-10 09:23:44 +03:00
static VALUE
2020-12-24 13:47:35 +03:00
pst_pid_m ( VALUE self )
2002-12-10 09:23:44 +03:00
{
2020-12-24 13:47:35 +03:00
rb_pid_t pid = pst_pid ( self ) ;
return PIDT2NUM ( pid ) ;
2002-12-10 09:23:44 +03:00
}
2018-02-02 19:14:21 +03:00
static VALUE pst_message_status ( VALUE str , int status ) ;
2007-10-15 05:31:11 +04:00
static void
pst_message ( VALUE str , rb_pid_t pid , int status )
2003-09-29 06:44:49 +04:00
{
2018-02-02 19:14:21 +03:00
rb_str_catf ( str , " pid %ld " , ( long ) pid ) ;
pst_message_status ( str , status ) ;
}
static VALUE
pst_message_status ( VALUE str , int status )
{
2003-09-29 06:44:49 +04:00
if ( WIFSTOPPED ( status ) ) {
2003-09-30 04:21:14 +04:00
int stopsig = WSTOPSIG ( status ) ;
2003-10-01 19:14:23 +04:00
const char * signame = ruby_signal_name ( stopsig ) ;
2003-09-30 04:21:14 +04:00
if ( signame ) {
* compile.c (insn_data_to_s_detail), file.c (rb_stat_inspect),
iseq.c (ruby_iseq_disasm_insn, ruby_iseq_disasm),
process.c (pst_message), re.c (match_inspect): use rb_str_catf.
* dir.c (dir_inspect), iseq.c (iseq_inspect, insn_operand_intern): use
rb_sprintf.
* error.c (rb_name_error, rb_raise, rb_loaderror, rb_fatal): use
rb_vsprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-07-22 12:53:34 +04:00
rb_str_catf ( str , " stopped SIG%s (signal %d) " , signame , stopsig ) ;
2003-09-30 04:21:14 +04:00
}
else {
* compile.c (insn_data_to_s_detail), file.c (rb_stat_inspect),
iseq.c (ruby_iseq_disasm_insn, ruby_iseq_disasm),
process.c (pst_message), re.c (match_inspect): use rb_str_catf.
* dir.c (dir_inspect), iseq.c (iseq_inspect, insn_operand_intern): use
rb_sprintf.
* error.c (rb_name_error, rb_raise, rb_loaderror, rb_fatal): use
rb_vsprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-07-22 12:53:34 +04:00
rb_str_catf ( str , " stopped signal %d " , stopsig ) ;
2003-09-30 04:21:14 +04:00
}
2003-09-29 06:44:49 +04:00
}
if ( WIFSIGNALED ( status ) ) {
int termsig = WTERMSIG ( status ) ;
2003-10-01 19:14:23 +04:00
const char * signame = ruby_signal_name ( termsig ) ;
2003-09-29 06:44:49 +04:00
if ( signame ) {
* compile.c (insn_data_to_s_detail), file.c (rb_stat_inspect),
iseq.c (ruby_iseq_disasm_insn, ruby_iseq_disasm),
process.c (pst_message), re.c (match_inspect): use rb_str_catf.
* dir.c (dir_inspect), iseq.c (iseq_inspect, insn_operand_intern): use
rb_sprintf.
* error.c (rb_name_error, rb_raise, rb_loaderror, rb_fatal): use
rb_vsprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-07-22 12:53:34 +04:00
rb_str_catf ( str , " SIG%s (signal %d) " , signame , termsig ) ;
2003-09-29 06:44:49 +04:00
}
else {
* compile.c (insn_data_to_s_detail), file.c (rb_stat_inspect),
iseq.c (ruby_iseq_disasm_insn, ruby_iseq_disasm),
process.c (pst_message), re.c (match_inspect): use rb_str_catf.
* dir.c (dir_inspect), iseq.c (iseq_inspect, insn_operand_intern): use
rb_sprintf.
* error.c (rb_name_error, rb_raise, rb_loaderror, rb_fatal): use
rb_vsprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-07-22 12:53:34 +04:00
rb_str_catf ( str , " signal %d " , termsig ) ;
2003-09-29 06:44:49 +04:00
}
}
if ( WIFEXITED ( status ) ) {
* compile.c (insn_data_to_s_detail), file.c (rb_stat_inspect),
iseq.c (ruby_iseq_disasm_insn, ruby_iseq_disasm),
process.c (pst_message), re.c (match_inspect): use rb_str_catf.
* dir.c (dir_inspect), iseq.c (iseq_inspect, insn_operand_intern): use
rb_sprintf.
* error.c (rb_name_error, rb_raise, rb_loaderror, rb_fatal): use
rb_vsprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-07-22 12:53:34 +04:00
rb_str_catf ( str , " exit %d " , WEXITSTATUS ( status ) ) ;
2003-09-29 06:44:49 +04:00
}
# ifdef WCOREDUMP
if ( WCOREDUMP ( status ) ) {
2007-10-15 05:31:11 +04:00
rb_str_cat2 ( str , " (core dumped) " ) ;
2003-09-29 06:44:49 +04:00
}
# endif
2018-02-02 19:14:21 +03:00
return str ;
2007-10-15 05:31:11 +04:00
}
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . to_s - > string
2007-10-15 05:31:11 +04:00
*
* Show pid and exit status as a string .
2010-09-12 04:15:27 +04:00
*
* system ( " false " )
* p $ ? . to_s # = > " pid 12766 exit 1 "
*
2007-10-15 05:31:11 +04:00
*/
static VALUE
pst_to_s ( VALUE st )
{
rb_pid_t pid ;
int status ;
VALUE str ;
2020-12-24 13:47:35 +03:00
pid = pst_pid ( st ) ;
2008-06-20 18:00:35 +04:00
status = PST2INT ( st ) ;
2007-10-15 05:31:11 +04:00
str = rb_str_buf_new ( 0 ) ;
pst_message ( str , pid , status ) ;
return str ;
}
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . inspect - > string
2007-10-15 05:31:11 +04:00
*
* Override the inspection method .
2010-09-12 04:15:27 +04:00
*
* system ( " false " )
* p $ ? . inspect # = > " #<Process::Status: pid 12861 exit 1> "
*
2007-10-15 05:31:11 +04:00
*/
static VALUE
pst_inspect ( VALUE st )
{
rb_pid_t pid ;
int status ;
2020-12-24 13:47:35 +03:00
VALUE str ;
2007-10-15 05:31:11 +04:00
2020-12-24 13:47:35 +03:00
pid = pst_pid ( st ) ;
if ( ! pid ) {
2008-08-21 14:18:38 +04:00
return rb_sprintf ( " #<%s: uninitialized> " , rb_class2name ( CLASS_OF ( st ) ) ) ;
}
2008-06-20 18:00:35 +04:00
status = PST2INT ( st ) ;
2007-10-15 05:31:11 +04:00
str = rb_sprintf ( " #<%s: " , rb_class2name ( CLASS_OF ( st ) ) ) ;
pst_message ( str , pid , status ) ;
2003-09-29 06:44:49 +04:00
rb_str_cat2 ( str , " > " ) ;
return str ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat = = other - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if the integer value of _stat_
* equals < em > other < / em > .
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_equal ( VALUE st1 , VALUE st2 )
2001-02-15 09:01:00 +03:00
{
if ( st1 = = st2 ) return Qtrue ;
return rb_equal ( pst_to_i ( st1 ) , st2 ) ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat & num - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Logical AND of the bits in _stat_ with < em > num < / em > .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { exit 0x37 }
* Process . wait
* sprintf ( ' % 04 x ' , $ ? . to_i ) # = > " 3700 "
* sprintf ( ' % 04 x ' , $ ? & 0x1e00 ) # = > " 1600 "
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_bitand ( VALUE st1 , VALUE st2 )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st1 ) & NUM2INT ( st2 ) ;
2001-02-15 09:01:00 +03:00
return INT2NUM ( status ) ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat > > num - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Shift the bits in _stat_ right < em > num < / em > places .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { exit 99 } # = > 26563
* Process . wait # = > 26563
* $ ? . to_i # = > 25344
* $ ? > > 8 # = > 99
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_rshift ( VALUE st1 , VALUE st2 )
2001-02-16 10:53:21 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st1 ) > > NUM2INT ( st2 ) ;
2001-02-16 10:53:21 +03:00
return INT2NUM ( status ) ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . stopped ? - > true or false
2004-06-29 05:17:39 +04:00
*
2019-03-28 06:33:35 +03:00
* Returns + true + if this process is stopped . This is only returned
* if the corresponding # wait call had the Process : : WUNTRACED flag
* set .
2004-01-02 09:01:12 +03:00
*/
2001-02-16 10:53:21 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wifstopped ( VALUE st )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2021-11-09 11:09:29 +03:00
return RBOOL ( WIFSTOPPED ( status ) ) ;
2001-02-15 09:01:00 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat . stopsig - > integer or nil
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the number of the signal that caused _stat_ to stop
* ( or + nil + if self is not stopped ) .
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wstopsig ( VALUE st )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2001-11-21 18:42:12 +03:00
if ( WIFSTOPPED ( status ) )
return INT2NUM ( WSTOPSIG ( status ) ) ;
return Qnil ;
2001-02-15 09:01:00 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . signaled ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if _stat_ terminated because of
* an uncaught signal .
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wifsignaled ( VALUE st )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2021-11-09 11:09:29 +03:00
return RBOOL ( WIFSIGNALED ( status ) ) ;
2001-02-15 09:01:00 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat . termsig - > integer or nil
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the number of the signal that caused _stat_ to
* terminate ( or + nil + if self was not terminated by an
* uncaught signal ) .
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wtermsig ( VALUE st )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2001-11-21 18:42:12 +03:00
if ( WIFSIGNALED ( status ) )
return INT2NUM ( WTERMSIG ( status ) ) ;
return Qnil ;
2001-02-15 09:01:00 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . exited ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if _stat_ exited normally ( for
* example using an < code > exit ( ) < / code > call or finishing the
* program ) .
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wifexited ( VALUE st )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2021-11-09 11:09:29 +03:00
return RBOOL ( WIFEXITED ( status ) ) ;
2001-02-15 09:01:00 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* stat . exitstatus - > integer or nil
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the least significant eight bits of the return code of
2019-03-28 06:33:35 +03:00
* _stat_ . Only available if # exited ? is + true + .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { } # = > 26572
* Process . wait # = > 26572
* $ ? . exited ? # = > true
* $ ? . exitstatus # = > 0
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { exit 99 } # = > 26573
* Process . wait # = > 26573
* $ ? . exited ? # = > true
* $ ? . exitstatus # = > 99
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wexitstatus ( VALUE st )
2001-02-15 09:01:00 +03:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2001-11-21 18:42:12 +03:00
if ( WIFEXITED ( status ) )
return INT2NUM ( WEXITSTATUS ( status ) ) ;
return Qnil ;
2001-02-15 09:01:00 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . success ? - > true , false or nil
2004-06-29 05:17:39 +04:00
*
2004-04-15 14:53:12 +04:00
* Returns + true + if _stat_ is successful , + false + if not .
2019-03-28 06:33:35 +03:00
* Returns + nil + if # exited ? is not + true + .
2004-04-15 14:53:12 +04:00
*/
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_success_p ( VALUE st )
2004-04-15 14:53:12 +04:00
{
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2004-04-15 14:53:12 +04:00
if ( ! WIFEXITED ( status ) )
return Qnil ;
2021-08-31 14:30:35 +03:00
return RBOOL ( WEXITSTATUS ( status ) = = EXIT_SUCCESS ) ;
2004-04-15 14:53:12 +04:00
}
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* stat . coredump ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if _stat_ generated a coredump
* when it terminated . Not available on all platforms .
*/
2001-02-15 09:01:00 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
pst_wcoredump ( VALUE st )
2001-02-15 09:01:00 +03:00
{
# ifdef WCOREDUMP
2008-06-20 18:00:35 +04:00
int status = PST2INT ( st ) ;
2001-02-15 09:01:00 +03:00
2021-11-09 11:09:29 +03:00
return RBOOL ( WCOREDUMP ( status ) ) ;
2001-02-15 09:01:00 +03:00
# else
return Qfalse ;
# endif
}
2015-09-08 10:15:09 +03:00
static rb_pid_t
do_waitpid ( rb_pid_t pid , int * st , int flags )
1998-01-16 15:13:05 +03:00
{
2014-12-27 11:03:29 +03:00
# if defined HAVE_WAITPID
2015-09-08 10:15:09 +03:00
return waitpid ( pid , st , flags ) ;
2014-12-27 11:03:29 +03:00
# elif defined HAVE_WAIT4
2015-09-08 10:15:09 +03:00
return wait4 ( pid , st , flags , NULL ) ;
2014-12-27 11:03:29 +03:00
# else
# error waitpid or wait4 is required.
1999-01-20 07:59:39 +03:00
# endif
2015-09-08 10:15:09 +03:00
}
* include/ruby/signal.h: removed.
* common.mk, class.c, eval.c, eval_intern.h, file.c, gc.c, hash.c,
io.c, process.c, signal.c: vm_core.h: ditto.
Some unused external global variables are also removed.
(rb_prohibit_interrupt, rb_trap_immediate, rb_trap_pending,
rb_thread_critical)
* ext/openssl/ossl_ssl.c, ext/openssl/ossl_x509store.c,
ext/readline/readline.c, ext/socket/depend,
ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19080 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-03 12:00:05 +04:00
2018-12-03 22:49:54 +03:00
# define WAITPID_LOCK_ONLY ((struct waitpid_state *)-1)
2018-07-05 06:02:33 +03:00
struct waitpid_state {
struct list_node wnode ;
rb_execution_context_t * ec ;
rb_nativethread_cond_t * cond ;
rb_pid_t ret ;
rb_pid_t pid ;
int status ;
int options ;
int errnum ;
} ;
2018-08-14 00:34:20 +03:00
int rb_sigwait_fd_get ( const rb_thread_t * ) ;
2018-10-19 23:14:41 +03:00
void rb_sigwait_sleep ( const rb_thread_t * , int fd , const rb_hrtime_t * ) ;
2018-08-14 00:34:20 +03:00
void rb_sigwait_fd_put ( const rb_thread_t * , int fd ) ;
2018-08-27 20:17:13 +03:00
void rb_thread_sleep_interruptible ( void ) ;
2018-08-14 00:34:20 +03:00
static int
2018-08-27 21:37:04 +03:00
waitpid_signal ( struct waitpid_state * w )
2018-08-14 00:34:20 +03:00
{
2018-08-27 21:37:04 +03:00
if ( w - > ec ) { /* rb_waitpid */
rb_threadptr_interrupt ( rb_ec_thread_ptr ( w - > ec ) ) ;
return TRUE ;
2018-08-14 00:34:20 +03:00
}
2018-08-27 21:37:04 +03:00
else { /* ruby_waitpid_locked */
if ( w - > cond ) {
rb_native_cond_signal ( w - > cond ) ;
return TRUE ;
}
}
return FALSE ;
2018-08-14 00:34:20 +03:00
}
2022-01-11 20:47:22 +03:00
// Used for VM memsize reporting. Returns the size of a list of waitpid_state
// structs. Defined here because the struct definition lives here as well.
size_t
rb_vm_memsize_waiting_list ( struct list_head * waiting_list )
{
struct waitpid_state * waitpid = 0 ;
size_t size = 0 ;
list_for_each ( waiting_list , waitpid , wnode ) {
size + = sizeof ( struct waitpid_state ) ;
}
return size ;
}
2018-08-14 00:34:20 +03:00
/*
* When a thread is done using sigwait_fd and there are other threads
* sleeping on waitpid , we must kick one of the threads out of
* rb_native_cond_wait so it can switch to rb_sigwait_sleep
*/
static void
sigwait_fd_migrate_sleeper ( rb_vm_t * vm )
{
struct waitpid_state * w = 0 ;
list_for_each ( & vm - > waiting_pids , w , wnode ) {
2018-08-27 21:37:04 +03:00
if ( waitpid_signal ( w ) ) return ;
2018-08-14 00:34:20 +03:00
}
list_for_each ( & vm - > waiting_grps , w , wnode ) {
2018-08-27 21:37:04 +03:00
if ( waitpid_signal ( w ) ) return ;
2018-08-14 00:34:20 +03:00
}
}
void
rb_sigwait_fd_migrate ( rb_vm_t * vm )
{
rb_native_mutex_lock ( & vm - > waitpid_lock ) ;
sigwait_fd_migrate_sleeper ( vm ) ;
rb_native_mutex_unlock ( & vm - > waitpid_lock ) ;
}
2018-07-05 06:02:33 +03:00
2018-08-21 16:39:24 +03:00
# if RUBY_SIGCHLD
2018-07-08 03:02:27 +03:00
extern volatile unsigned int ruby_nocldwait ; /* signal.c */
2018-08-14 00:34:20 +03:00
/* called by timer thread or thread which acquired sigwait_fd */
2018-07-05 06:02:33 +03:00
static void
waitpid_each ( struct list_head * head )
{
struct waitpid_state * w = 0 , * next ;
list_for_each_safe ( head , w , next , wnode ) {
2018-08-26 07:29:11 +03:00
rb_pid_t ret = do_waitpid ( w - > pid , & w - > status , w - > options | WNOHANG ) ;
2018-07-05 06:02:33 +03:00
if ( ! ret ) continue ;
if ( ret = = - 1 ) w - > errnum = errno ;
2018-08-27 20:17:13 +03:00
w - > ret = ret ;
list_del_init ( & w - > wnode ) ;
2018-08-27 21:37:04 +03:00
waitpid_signal ( w ) ;
2018-07-05 06:02:33 +03:00
}
}
2018-08-21 16:39:24 +03:00
# else
# define ruby_nocldwait 0
# endif
2018-07-05 06:02:33 +03:00
void
ruby_waitpid_all ( rb_vm_t * vm )
{
2018-08-21 16:39:24 +03:00
# if RUBY_SIGCHLD
2018-07-05 06:02:33 +03:00
rb_native_mutex_lock ( & vm - > waitpid_lock ) ;
waitpid_each ( & vm - > waiting_pids ) ;
if ( list_empty ( & vm - > waiting_pids ) ) {
waitpid_each ( & vm - > waiting_grps ) ;
}
2018-07-08 03:02:27 +03:00
/* emulate SA_NOCLDWAIT */
if ( list_empty ( & vm - > waiting_pids ) & & list_empty ( & vm - > waiting_grps ) ) {
while ( ruby_nocldwait & & do_waitpid ( - 1 , 0 , WNOHANG ) > 0 )
; /* keep looping */
}
2018-07-05 06:02:33 +03:00
rb_native_mutex_unlock ( & vm - > waitpid_lock ) ;
2018-08-21 16:39:24 +03:00
# endif
2018-07-05 06:02:33 +03:00
}
static void
waitpid_state_init ( struct waitpid_state * w , rb_pid_t pid , int options )
{
w - > ret = 0 ;
w - > pid = pid ;
w - > options = options ;
2020-12-07 23:29:09 +03:00
w - > errnum = 0 ;
2020-12-24 10:44:38 +03:00
w - > status = 0 ;
2018-07-05 06:02:33 +03:00
}
2018-10-19 23:14:41 +03:00
static const rb_hrtime_t *
2018-08-14 00:34:20 +03:00
sigwait_sleep_time ( void )
{
if ( SIGCHLD_LOSSY ) {
2018-10-19 23:14:41 +03:00
static const rb_hrtime_t busy_wait = 100 * RB_HRTIME_PER_MSEC ;
2018-08-14 00:34:20 +03:00
return & busy_wait ;
}
return 0 ;
}
2018-07-05 06:02:33 +03:00
/*
* must be called with vm - > waitpid_lock held , this is not interruptible
*/
rb_pid_t
ruby_waitpid_locked ( rb_vm_t * vm , rb_pid_t pid , int * status , int options ,
rb_nativethread_cond_t * cond )
{
struct waitpid_state w ;
assert ( ! ruby_thread_has_gvl_p ( ) & & " must not have GVL " ) ;
waitpid_state_init ( & w , pid , options ) ;
if ( w . pid > 0 | | list_empty ( & vm - > waiting_pids ) )
w . ret = do_waitpid ( w . pid , & w . status , w . options | WNOHANG ) ;
if ( w . ret ) {
if ( w . ret = = - 1 ) w . errnum = errno ;
}
else {
2018-08-27 20:17:13 +03:00
int sigwait_fd = - 1 ;
2018-07-05 06:02:33 +03:00
w . ec = 0 ;
list_add ( w . pid > 0 ? & vm - > waiting_pids : & vm - > waiting_grps , & w . wnode ) ;
do {
2018-08-27 20:17:13 +03:00
if ( sigwait_fd < 0 )
sigwait_fd = rb_sigwait_fd_get ( 0 ) ;
2018-08-14 00:34:20 +03:00
2018-08-27 20:17:13 +03:00
if ( sigwait_fd > = 0 ) {
2018-08-14 00:34:20 +03:00
w . cond = 0 ;
rb_native_mutex_unlock ( & vm - > waitpid_lock ) ;
2018-08-27 20:17:13 +03:00
rb_sigwait_sleep ( 0 , sigwait_fd , sigwait_sleep_time ( ) ) ;
2018-08-14 00:34:20 +03:00
rb_native_mutex_lock ( & vm - > waitpid_lock ) ;
}
else {
w . cond = cond ;
rb_native_cond_wait ( w . cond , & vm - > waitpid_lock ) ;
}
2018-07-05 06:02:33 +03:00
} while ( ! w . ret ) ;
list_del ( & w . wnode ) ;
2018-08-14 00:34:20 +03:00
/* we're done, maybe other waitpid callers are not: */
2018-08-27 20:17:13 +03:00
if ( sigwait_fd > = 0 ) {
rb_sigwait_fd_put ( 0 , sigwait_fd ) ;
2018-08-14 00:34:20 +03:00
sigwait_fd_migrate_sleeper ( vm ) ;
}
2018-07-05 06:02:33 +03:00
}
if ( status ) {
* status = w . status ;
}
if ( w . ret = = - 1 ) errno = w . errnum ;
return w . ret ;
}
static VALUE
waitpid_sleep ( VALUE x )
2018-06-27 06:14:30 +03:00
{
2018-07-05 06:02:33 +03:00
struct waitpid_state * w = ( struct waitpid_state * ) x ;
while ( ! w - > ret ) {
2018-08-27 20:17:13 +03:00
rb_thread_sleep_interruptible ( ) ;
2018-07-05 06:02:33 +03:00
}
return Qfalse ;
}
static VALUE
waitpid_cleanup ( VALUE x )
{
struct waitpid_state * w = ( struct waitpid_state * ) x ;
2018-09-19 11:23:19 +03:00
/*
* XXX w - > ret is sometimes set but list_del is still needed , here ,
* Not sure why , so we unconditionally do list_del here :
*/
if ( TRUE | | w - > ret = = 0 ) {
2018-07-05 06:02:33 +03:00
rb_vm_t * vm = rb_ec_vm_ptr ( w - > ec ) ;
rb_native_mutex_lock ( & vm - > waitpid_lock ) ;
list_del ( & w - > wnode ) ;
rb_native_mutex_unlock ( & vm - > waitpid_lock ) ;
}
2018-07-30 09:35:08 +03:00
2018-07-05 06:02:33 +03:00
return Qfalse ;
}
static void
waitpid_wait ( struct waitpid_state * w )
{
rb_vm_t * vm = rb_ec_vm_ptr ( w - > ec ) ;
2018-08-27 20:17:13 +03:00
int need_sleep = FALSE ;
2018-07-05 06:02:33 +03:00
/*
* Lock here to prevent do_waitpid from stealing work from the
* ruby_waitpid_locked done by mjit workers since mjit works
* outside of GVL
*/
rb_native_mutex_lock ( & vm - > waitpid_lock ) ;
2020-12-07 23:29:09 +03:00
if ( w - > pid > 0 | | list_empty ( & vm - > waiting_pids ) ) {
2018-07-05 06:02:33 +03:00
w - > ret = do_waitpid ( w - > pid , & w - > status , w - > options | WNOHANG ) ;
2020-12-07 23:29:09 +03:00
}
2018-07-05 06:02:33 +03:00
if ( w - > ret ) {
if ( w - > ret = = - 1 ) w - > errnum = errno ;
}
else if ( w - > options & WNOHANG ) {
}
else {
2018-08-27 20:17:13 +03:00
need_sleep = TRUE ;
}
if ( need_sleep ) {
w - > cond = 0 ;
2018-07-05 06:02:33 +03:00
/* order matters, favor specified PIDs rather than -1 or 0 */
list_add ( w - > pid > 0 ? & vm - > waiting_pids : & vm - > waiting_grps , & w - > wnode ) ;
}
rb_native_mutex_unlock ( & vm - > waitpid_lock ) ;
2018-08-27 20:17:13 +03:00
if ( need_sleep ) {
2018-07-05 06:02:33 +03:00
rb_ensure ( waitpid_sleep , ( VALUE ) w , waitpid_cleanup , ( VALUE ) w ) ;
}
}
static void *
waitpid_blocking_no_SIGCHLD ( void * x )
{
struct waitpid_state * w = x ;
w - > ret = do_waitpid ( w - > pid , & w - > status , w - > options ) ;
return 0 ;
}
static void
waitpid_no_SIGCHLD ( struct waitpid_state * w )
{
if ( w - > options & WNOHANG ) {
w - > ret = do_waitpid ( w - > pid , & w - > status , w - > options ) ;
}
else {
do {
rb_thread_call_without_gvl ( waitpid_blocking_no_SIGCHLD , w ,
RUBY_UBF_PROCESS , 0 ) ;
} while ( w - > ret < 0 & & errno = = EINTR & & ( RUBY_VM_CHECK_INTS ( w - > ec ) , 1 ) ) ;
}
if ( w - > ret = = - 1 )
w - > errnum = errno ;
2015-09-08 10:00:13 +03:00
}
2020-12-11 13:40:25 +03:00
VALUE
rb_process_status_wait ( rb_pid_t pid , int flags )
{
// We only enter the scheduler if we are "blocking":
if ( ! ( flags & WNOHANG ) ) {
2021-02-09 09:39:56 +03:00
VALUE scheduler = rb_fiber_scheduler_current ( ) ;
VALUE result = rb_fiber_scheduler_process_wait ( scheduler , pid , flags ) ;
if ( result ! = Qundef ) return result ;
2020-12-11 13:40:25 +03:00
}
2021-06-26 01:17:26 +03:00
struct waitpid_state waitpid_state ;
2020-12-11 13:40:25 +03:00
2021-06-26 01:17:26 +03:00
waitpid_state_init ( & waitpid_state , pid , flags ) ;
waitpid_state . ec = GET_EC ( ) ;
2020-12-11 13:40:25 +03:00
if ( WAITPID_USE_SIGCHLD ) {
2021-06-26 01:17:26 +03:00
waitpid_wait ( & waitpid_state ) ;
2020-12-11 13:40:25 +03:00
}
else {
2021-06-26 01:17:26 +03:00
waitpid_no_SIGCHLD ( & waitpid_state ) ;
2020-12-11 13:40:25 +03:00
}
2021-06-26 01:17:26 +03:00
if ( waitpid_state . ret = = 0 ) return Qnil ;
2020-12-11 13:40:25 +03:00
2021-06-26 01:17:26 +03:00
if ( waitpid_state . ret > 0 & & ruby_nocldwait ) {
waitpid_state . ret = - 1 ;
waitpid_state . errnum = ECHILD ;
2020-12-24 10:44:38 +03:00
}
2021-06-26 01:17:26 +03:00
return rb_process_status_new ( waitpid_state . ret , waitpid_state . status , waitpid_state . errnum ) ;
2020-12-11 13:40:25 +03:00
}
2020-12-07 23:29:09 +03:00
/*
* call - seq :
* Process : : Status . wait ( pid = - 1 , flags = 0 ) - > Process : : Status
*
* Waits for a child process to exit and returns a Process : : Status object
* containing information on that process . Which child it waits on
* depends on the value of _pid_ :
*
* > 0 : : Waits for the child whose process ID equals _pid_ .
*
* 0 : : Waits for any child whose process group ID equals that of the
* calling process .
*
* - 1 : : Waits for any child process ( the default if no _pid_ is
* given ) .
*
* < - 1 : : Waits for any child whose process group ID equals the absolute
* value of _pid_ .
*
* The _flags_ argument may be a logical or of the flag values
* Process : : WNOHANG ( do not block if no child available )
* or Process : : WUNTRACED ( return stopped children that
* haven ' t been reported ) . Not all flags are available on all
* platforms , but a flag value of zero will work on all platforms .
*
2020-12-12 05:44:25 +03:00
* Returns + nil + if there are no child processes .
* Not available on all platforms .
2020-12-07 23:29:09 +03:00
*
* May invoke the scheduler hook _process_wait_ .
*
* fork { exit 99 } # = > 27429
* Process : : Status . wait # = > pid 27429 exit 99
* $ ? # = > nil
*
* pid = fork { sleep 3 } # = > 27440
* Time . now # = > 2008 - 03 - 08 19 : 56 : 16 + 0900
* Process : : Status . wait ( pid , Process : : WNOHANG ) # = > nil
* Time . now # = > 2008 - 03 - 08 19 : 56 : 16 + 0900
* Process : : Status . wait ( pid , 0 ) # = > pid 27440 exit 99
* Time . now # = > 2008 - 03 - 08 19 : 56 : 19 + 0900
2020-12-09 05:49:20 +03:00
*
2020-12-12 05:44:25 +03:00
* This is an EXPERIMENTAL FEATURE .
2020-12-07 23:29:09 +03:00
*/
VALUE
rb_process_status_waitv ( int argc , VALUE * argv , VALUE _ )
{
rb_check_arity ( argc , 0 , 2 ) ;
rb_pid_t pid = - 1 ;
int flags = 0 ;
if ( argc > = 1 ) {
pid = NUM2PIDT ( argv [ 0 ] ) ;
}
if ( argc > = 2 ) {
flags = RB_NUM2INT ( argv [ 1 ] ) ;
}
return rb_process_status_wait ( pid , flags ) ;
}
rb_pid_t
rb_waitpid ( rb_pid_t pid , int * st , int flags )
{
VALUE status = rb_process_status_wait ( pid , flags ) ;
2020-12-24 10:44:38 +03:00
if ( NIL_P ( status ) ) return 0 ;
2020-12-11 13:54:14 +03:00
2020-12-07 23:29:09 +03:00
struct rb_process_status * data = RTYPEDDATA_DATA ( status ) ;
2020-12-11 13:54:14 +03:00
pid = data - > pid ;
2020-12-07 23:29:09 +03:00
if ( st ) * st = data - > status ;
2020-12-24 10:44:38 +03:00
if ( pid = = - 1 ) {
errno = data - > error ;
}
else {
GET_THREAD ( ) - > last_status = status ;
}
2020-12-07 23:29:09 +03:00
2020-12-11 13:54:14 +03:00
return pid ;
1998-01-16 15:13:05 +03:00
}
2019-08-29 04:23:14 +03:00
static VALUE
proc_wait ( int argc , VALUE * argv )
{
rb_pid_t pid ;
int flags , status ;
flags = 0 ;
if ( rb_check_arity ( argc , 0 , 2 ) = = 0 ) {
pid = - 1 ;
}
else {
VALUE vflags ;
pid = NUM2PIDT ( argv [ 0 ] ) ;
if ( argc = = 2 & & ! NIL_P ( vflags = argv [ 1 ] ) ) {
flags = NUM2UINT ( vflags ) ;
}
}
2020-12-07 23:29:09 +03:00
2019-08-29 04:23:14 +03:00
if ( ( pid = rb_waitpid ( pid , & status , flags ) ) < 0 )
rb_sys_fail ( 0 ) ;
2020-12-07 23:29:09 +03:00
2019-08-29 04:23:14 +03:00
if ( pid = = 0 ) {
rb_last_status_clear ( ) ;
return Qnil ;
}
2020-12-07 23:29:09 +03:00
2019-08-29 04:23:14 +03:00
return PIDT2NUM ( pid ) ;
}
2004-01-02 09:01:12 +03:00
/* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
has historically been documented as if it didn ' t take any arguments
despite the fact that it ' s just an alias for : : waitpid ( ) . The way I
have it below is more truthful , but a little confusing .
I also took the liberty of putting in the pid values , as they ' re
pretty useful , and it looked as if the original ' ri ' output was
supposed to contain them after " [...]depending on the value of
aPid : " .
The ' ansi ' and ' bs ' formats of the ri output don ' t display the
definition list for some reason , but the plain text one does .
*/
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . wait ( ) - > integer
* Process . wait ( pid = - 1 , flags = 0 ) - > integer
* Process . waitpid ( pid = - 1 , flags = 0 ) - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Waits for a child process to exit , returns its process id , and
2019-03-28 06:33:35 +03:00
* sets < code > $ ? < / code > to a Process : : Status object
2004-01-02 09:01:12 +03:00
* containing information on that process . Which child it waits on
* depends on the value of _pid_ :
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* > 0 : : Waits for the child whose process ID equals _pid_ .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* 0 : : Waits for any child whose process group ID equals that of the
* calling process .
*
* - 1 : : Waits for any child process ( the default if no _pid_ is
* given ) .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* < - 1 : : Waits for any child whose process group ID equals the absolute
* value of _pid_ .
*
* The _flags_ argument may be a logical or of the flag values
2019-03-28 06:33:35 +03:00
* Process : : WNOHANG ( do not block if no child available )
* or Process : : WUNTRACED ( return stopped children that
2004-01-02 09:01:12 +03:00
* haven ' t been reported ) . Not all flags are available on all
* platforms , but a flag value of zero will work on all platforms .
2004-06-29 05:17:39 +04:00
*
2012-02-14 01:24:01 +04:00
* Calling this method raises a SystemCallError if there are no child
* processes . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* include Process
* fork { exit 99 } # = > 27429
* wait # = > 27429
* $ ? . exitstatus # = > 99
*
* pid = fork { sleep 3 } # = > 27440
2008-03-09 04:04:46 +03:00
* Time . now # = > 2008 - 03 - 08 19 : 56 : 16 + 0900
2004-01-02 09:01:12 +03:00
* waitpid ( pid , Process : : WNOHANG ) # = > nil
2008-03-09 04:04:46 +03:00
* Time . now # = > 2008 - 03 - 08 19 : 56 : 16 + 0900
2004-01-02 09:01:12 +03:00
* waitpid ( pid , 0 ) # = > 27440
2008-03-09 04:04:46 +03:00
* Time . now # = > 2008 - 03 - 08 19 : 56 : 19 + 0900
2004-01-02 09:01:12 +03:00
*/
2019-08-28 11:48:48 +03:00
static VALUE
proc_m_wait ( int c , VALUE * v , VALUE _ )
{
return proc_wait ( c , v ) ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . wait2 ( pid = - 1 , flags = 0 ) - > [ pid , status ]
* Process . waitpid2 ( pid = - 1 , flags = 0 ) - > [ pid , status ]
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Waits for a child process to exit ( see Process : : waitpid for exact
* semantics ) and returns an array containing the process id and the
2019-03-28 06:33:35 +03:00
* exit status ( a Process : : Status object ) of that
2012-02-14 01:24:01 +04:00
* child . Raises a SystemCallError if there are no child processes .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . fork { exit 99 } # = > 27437
* pid , status = Process . wait2
* pid # = > 27437
* status . exitstatus # = > 99
*/
2000-06-19 12:38:11 +04:00
static VALUE
2019-08-28 11:48:48 +03:00
proc_wait2 ( int argc , VALUE * argv , VALUE _ )
2000-06-19 12:38:11 +04:00
{
2001-08-06 07:05:23 +04:00
VALUE pid = proc_wait ( argc , argv ) ;
2000-11-27 12:23:38 +03:00
if ( NIL_P ( pid ) ) return Qnil ;
2007-02-08 09:48:34 +03:00
return rb_assoc_new ( pid , rb_last_status_get ( ) ) ;
2000-06-19 12:38:11 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . waitall - > [ [ pid1 , status1 ] , . . . ]
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Waits for all children , returning an array of
* _pid_ / _status_ pairs ( where _status_ is a
2019-03-28 06:33:35 +03:00
* Process : : Status object ) .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* fork { sleep 0.2 ; exit 2 } # = > 27432
* fork { sleep 0.1 ; exit 1 } # = > 27433
* fork { exit 0 } # = > 27434
* p Process . waitall
*
* < em > produces < / em > :
*
2010-12-29 04:33:28 +03:00
* [ [ 30982 , # < Process : : Status : pid 30982 exit 0 > ] ,
* [ 30979 , # < Process : : Status : pid 30979 exit 1 > ] ,
* [ 30976 , # < Process : : Status : pid 30976 exit 2 > ] ]
2004-01-02 09:01:12 +03:00
*/
2001-02-15 09:01:00 +03:00
static VALUE
2019-08-28 11:48:48 +03:00
proc_waitall ( VALUE _ )
2001-02-15 09:01:00 +03:00
{
2001-05-02 08:22:21 +04:00
VALUE result ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t pid ;
int status ;
2001-02-15 09:01:00 +03:00
2001-05-02 08:22:21 +04:00
result = rb_ary_new ( ) ;
2007-08-18 11:44:51 +04:00
rb_last_status_clear ( ) ;
2001-02-15 09:01:00 +03:00
for ( pid = - 1 ; ; ) {
2007-08-18 11:44:51 +04:00
pid = rb_waitpid ( - 1 , & status , 0 ) ;
2001-02-15 09:01:00 +03:00
if ( pid = = - 1 ) {
2015-12-23 11:57:48 +03:00
int e = errno ;
if ( e = = ECHILD )
2001-02-15 09:01:00 +03:00
break ;
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( e , 0 ) ;
2001-02-15 09:01:00 +03:00
}
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_ary_push ( result , rb_assoc_new ( PIDT2NUM ( pid ) , rb_last_status_get ( ) ) ) ;
2001-05-02 08:22:21 +04:00
}
return result ;
2001-02-15 09:01:00 +03:00
}
2014-09-12 23:42:01 +04:00
static VALUE rb_cWaiter ;
2008-06-20 07:40:02 +04:00
static VALUE
detach_process_pid ( VALUE thread )
{
2014-11-24 06:44:24 +03:00
return rb_thread_local_aref ( thread , id_pid ) ;
2008-06-20 07:40:02 +04:00
}
2003-03-07 08:59:42 +03:00
static VALUE
2007-08-18 10:59:54 +04:00
detach_process_watcher ( void * arg )
2003-03-07 08:59:42 +03:00
{
2007-09-26 22:17:43 +04:00
rb_pid_t cpid , pid = ( rb_pid_t ) ( VALUE ) arg ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
int status ;
2003-03-07 08:59:42 +03:00
2007-08-18 10:59:54 +04:00
while ( ( cpid = rb_waitpid ( pid , & status , 0 ) ) = = 0 ) {
/* wait while alive */
2003-03-07 08:59:42 +03:00
}
2007-08-18 10:59:54 +04:00
return rb_last_status_get ( ) ;
2003-03-07 08:59:42 +03:00
}
2003-03-20 09:27:22 +03:00
VALUE
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_detach_process ( rb_pid_t pid )
2003-03-07 08:59:42 +03:00
{
2008-06-20 07:40:02 +04:00
VALUE watcher = rb_thread_create ( detach_process_watcher , ( void * ) ( VALUE ) pid ) ;
2014-11-24 06:44:24 +03:00
rb_thread_local_aset ( watcher , id_pid , PIDT2NUM ( pid ) ) ;
2014-09-12 23:42:01 +04:00
RBASIC_SET_CLASS ( watcher , rb_cWaiter ) ;
2008-06-20 07:40:02 +04:00
return watcher ;
2003-03-07 08:59:42 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . detach ( pid ) - > thread
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Some operating systems retain the status of terminated child
* processes until the parent collects that status ( normally using
2014-12-29 04:37:07 +03:00
* some variant of < code > wait ( ) < / code > ) . If the parent never collects
2004-01-02 09:01:12 +03:00
* this status , the child stays around as a < em > zombie < / em > process .
2019-03-28 06:33:35 +03:00
* Process : : detach prevents this by setting up a separate Ruby thread
* whose sole job is to reap the status of the process _pid_ when it
* terminates . Use # detach only when you do not intend to explicitly
* wait for the child to terminate .
2004-02-09 10:30:17 +03:00
*
* The waiting thread returns the exit status of the detached process
2019-03-28 06:33:35 +03:00
* when it terminates , so you can use Thread # join to
2004-02-09 10:30:17 +03:00
* know the result . If specified _pid_ is not a valid child process
* ID , the thread returns + nil + immediately .
*
2019-03-28 06:33:35 +03:00
* The waiting thread has # pid method which returns the pid .
2009-02-24 14:00:24 +03:00
*
2004-01-02 09:01:12 +03:00
* In this first example , we don ' t reap the first child process , so
* it appears as a zombie in the process status display .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* p1 = fork { sleep 0.1 }
* p2 = fork { sleep 0.2 }
* Process . waitpid ( p2 )
* sleep 2
* system ( " ps -ho pid,state -p #{p1} " )
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* < em > produces : < / em >
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* 27389 Z
2004-06-29 05:17:39 +04:00
*
2019-03-28 06:33:35 +03:00
* In the next example , Process : : detach is used to reap
2004-01-02 09:01:12 +03:00
* the child automatically .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* p1 = fork { sleep 0.1 }
* p2 = fork { sleep 0.2 }
* Process . detach ( p1 )
* Process . waitpid ( p2 )
* sleep 2
* system ( " ps -ho pid,state -p #{p1} " )
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* < em > ( produces no output ) < / em >
*/
2003-03-07 08:59:42 +03:00
static VALUE
2005-08-31 05:40:56 +04:00
proc_detach ( VALUE obj , VALUE pid )
2003-03-07 08:59:42 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return rb_detach_process ( NUM2PIDT ( pid ) ) ;
2003-03-07 08:59:42 +03:00
}
2012-06-09 18:45:46 +04:00
/* This function should be async-signal-safe. Actually it is. */
2012-06-27 09:37:15 +04:00
static void
before_exec_async_signal_safe ( void )
2011-05-28 17:52:03 +04:00
{
2012-06-09 18:45:46 +04:00
}
2011-05-28 19:24:18 +04:00
2012-06-27 09:37:15 +04:00
static void
2014-09-30 09:25:32 +04:00
before_exec_non_async_signal_safe ( void )
2012-06-09 18:45:46 +04:00
{
2014-09-03 13:56:38 +04:00
/*
* On Mac OS X 10.5 . x ( Leopard ) or earlier , exec ( ) may return ENOTSUP
* if the process have multiple threads . Therefore we have to kill
* internal threads temporary . [ ruby - core : 10583 ]
* This is also true on Haiku . It returns Errno : : EPERM against exec ( )
* in multiple threads .
2015-08-14 12:44:10 +03:00
*
* Nowadays , we always stop the timer thread completely to allow redirects .
2014-09-03 13:56:38 +04:00
*/
2015-08-14 12:44:10 +03:00
rb_thread_stop_timer_thread ( ) ;
2011-05-28 17:52:03 +04:00
}
2018-11-22 11:46:51 +03:00
# define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
# ifdef _WIN32
int rb_w32_set_nonblock2 ( int fd , int nonblock ) ;
# endif
static int
set_blocking ( int fd )
{
# ifdef _WIN32
return rb_w32_set_nonblock2 ( fd , 0 ) ;
# elif defined(F_GETFL) && defined(F_SETFL)
int fl = fcntl ( fd , F_GETFL ) ; /* async-signal-safe */
/* EBADF ought to be possible */
if ( fl = = - 1 ) return fl ;
if ( fl & O_NONBLOCK ) {
fl & = ~ O_NONBLOCK ;
return fcntl ( fd , F_SETFL , fl ) ;
}
return 0 ;
# endif
}
static void
stdfd_clear_nonblock ( void )
{
/* many programs cannot deal with non-blocking stdin/stdout/stderr */
int fd ;
for ( fd = 0 ; fd < 3 ; fd + + ) {
( void ) set_blocking ( fd ) ; /* can't do much about errors anyhow */
}
}
2012-06-27 09:37:15 +04:00
static void
2014-09-30 09:25:32 +04:00
before_exec ( void )
2012-06-09 18:45:46 +04:00
{
before_exec_non_async_signal_safe ( ) ;
before_exec_async_signal_safe ( ) ;
}
2012-06-10 01:48:42 +04:00
/* This function should be async-signal-safe. Actually it is. */
2012-06-27 09:37:15 +04:00
static void
after_exec_async_signal_safe ( void )
2011-05-28 17:52:03 +04:00
{
2012-06-10 01:48:42 +04:00
}
2012-06-27 09:37:15 +04:00
static void
after_exec_non_async_signal_safe ( void )
2012-06-10 01:48:42 +04:00
{
rb_thread_reset_timer_thread ( ) ;
rb_thread_start_timer_thread ( ) ;
2011-05-28 17:52:03 +04:00
}
2012-06-27 09:37:15 +04:00
static void
after_exec ( void )
2012-06-10 01:48:42 +04:00
{
after_exec_async_signal_safe ( ) ;
after_exec_non_async_signal_safe ( ) ;
}
2018-07-26 15:04:32 +03:00
# if defined HAVE_WORKING_FORK || defined HAVE_DAEMON
2020-12-05 19:16:33 +03:00
static void
before_fork_ruby ( void )
{
before_exec ( ) ;
}
2018-06-24 13:30:48 +03:00
static void
2018-11-20 03:04:19 +03:00
after_fork_ruby ( void )
2018-06-24 13:30:48 +03:00
{
rb_threadptr_pending_interrupt_clear ( GET_THREAD ( ) ) ;
after_exec ( ) ;
}
2018-07-26 15:04:32 +03:00
# endif
1998-01-16 15:13:05 +03:00
2017-10-23 08:56:25 +03:00
# if defined(HAVE_WORKING_FORK)
2012-06-05 14:16:11 +04:00
2012-06-06 15:58:09 +04:00
/* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/
2017-11-14 07:42:38 +03:00
# define try_with_sh(err, prog, argv, envp) ((err == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0)
2010-11-04 19:21:38 +03:00
static void
2012-06-06 15:09:26 +04:00
exec_with_sh ( const char * prog , char * * argv , char * * envp )
2010-11-04 19:21:38 +03:00
{
* argv = ( char * ) prog ;
* - - argv = ( char * ) " sh " ;
2012-06-06 15:09:26 +04:00
if ( envp )
execve ( " /bin/sh " , argv , envp ) ; /* async-signal-safe */
else
2015-06-19 20:49:27 +03:00
execv ( " /bin/sh " , argv ) ; /* async-signal-safe (since SUSv4) */
2010-11-04 19:21:38 +03:00
}
2012-06-05 14:16:11 +04:00
2010-11-04 19:21:38 +03:00
# else
2018-02-13 10:42:51 +03:00
# define try_with_sh(err, prog, argv, envp) (void)0
2010-11-04 19:21:38 +03:00
# endif
2012-06-09 05:40:22 +04:00
/* This function should be async-signal-safe. Actually it is. */
2012-05-17 06:48:59 +04:00
static int
2012-06-06 16:33:28 +04:00
proc_exec_cmd ( const char * prog , VALUE argv_str , VALUE envp_str )
2012-05-17 06:48:59 +04:00
{
2012-06-03 18:53:13 +04:00
char * * argv ;
2016-10-14 18:54:03 +03:00
# ifndef _WIN32
2012-06-06 15:09:26 +04:00
char * * envp ;
2017-11-14 07:42:38 +03:00
int err ;
2016-10-14 18:54:03 +03:00
# endif
2008-05-08 01:43:54 +04:00
2012-06-04 14:19:32 +04:00
argv = ARGVSTR2ARGV ( argv_str ) ;
2012-06-03 18:53:13 +04:00
2004-02-16 09:45:32 +03:00
if ( ! prog ) {
2017-11-14 07:42:38 +03:00
return ENOENT ;
2004-02-16 09:45:32 +03:00
}
2003-01-06 07:30:27 +03:00
2016-10-14 18:54:03 +03:00
# ifdef _WIN32
rb_w32_uaspawn ( P_OVERLAY , prog , argv ) ;
2017-11-14 07:42:38 +03:00
return errno ;
2016-10-14 18:54:03 +03:00
# else
2018-05-14 06:30:03 +03:00
envp = envp_str ? RB_IMEMO_TMPBUF_PTR ( envp_str ) : NULL ;
2012-06-03 12:29:48 +04:00
if ( envp_str )
2012-06-06 15:09:26 +04:00
execve ( prog , argv , envp ) ; /* async-signal-safe */
2012-06-03 12:29:48 +04:00
else
2015-06-19 20:49:27 +03:00
execv ( prog , argv ) ; /* async-signal-safe (since SUSv4) */
2017-11-14 07:42:38 +03:00
err = errno ;
try_with_sh ( err , prog , argv , envp ) ; /* try_with_sh() is async-signal-safe. */
return err ;
2016-10-14 18:54:03 +03:00
# endif
2012-06-04 09:46:24 +04:00
}
1998-01-16 15:13:05 +03:00
2012-06-09 05:40:22 +04:00
/* This function should be async-signal-safe. Actually it is. */
2012-06-03 15:12:20 +04:00
static int
2012-06-06 16:33:28 +04:00
proc_exec_sh ( const char * str , VALUE envp_str )
2012-05-17 06:48:59 +04:00
{
2012-06-14 17:11:41 +04:00
const char * s ;
2012-06-08 20:26:01 +04:00
2012-06-14 17:11:41 +04:00
s = str ;
while ( * s = = ' ' | | * s = = ' \t ' | | * s = = ' \n ' )
s + + ;
2001-02-19 10:03:06 +03:00
2012-06-14 17:11:41 +04:00
if ( ! * s ) {
2017-11-14 07:42:38 +03:00
return ENOENT ;
2012-06-03 18:53:13 +04:00
}
2003-01-06 07:30:27 +03:00
# ifdef _WIN32
2013-06-30 05:59:21 +04:00
rb_w32_uspawn ( P_OVERLAY , ( char * ) str , 0 ) ;
2017-11-14 07:42:38 +03:00
# elif defined(__CYGWIN32__)
2012-06-03 18:53:13 +04:00
{
char fbuf [ MAXPATHLEN ] ;
char * shell = dln_find_exe_r ( " sh " , 0 , fbuf , sizeof ( fbuf ) ) ;
int status = - 1 ;
if ( shell )
execl ( shell , " sh " , " -c " , str , ( char * ) NULL ) ;
else
status = system ( str ) ;
if ( status ! = - 1 )
exit ( status ) ;
}
1998-01-16 15:13:05 +03:00
# else
2012-06-03 18:53:13 +04:00
if ( envp_str )
2018-05-14 06:30:03 +03:00
execle ( " /bin/sh " , " sh " , " -c " , str , ( char * ) NULL , RB_IMEMO_TMPBUF_PTR ( envp_str ) ) ; /* async-signal-safe */
2012-06-03 18:53:13 +04:00
else
2015-06-19 20:49:27 +03:00
execl ( " /bin/sh " , " sh " , " -c " , str , ( char * ) NULL ) ; /* async-signal-safe (since SUSv4) */
2003-01-06 07:30:27 +03:00
# endif /* _WIN32 */
2017-11-14 07:42:38 +03:00
return errno ;
2012-06-04 09:46:24 +04:00
}
1998-01-16 15:13:05 +03:00
2012-06-03 15:12:20 +04:00
int
rb_proc_exec ( const char * str )
{
2012-06-09 04:01:58 +04:00
int ret ;
before_exec ( ) ;
ret = proc_exec_sh ( str , Qfalse ) ;
2017-11-14 07:42:38 +03:00
after_exec ( ) ;
errno = ret ;
return - 1 ;
2012-06-03 15:12:20 +04:00
}
2012-06-20 14:31:02 +04:00
static void
mark_exec_arg ( void * ptr )
{
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp = ptr ;
if ( eargp - > use_shell )
rb_gc_mark ( eargp - > invoke . sh . shell_script ) ;
2012-06-20 14:31:02 +04:00
else {
2012-06-23 03:09:16 +04:00
rb_gc_mark ( eargp - > invoke . cmd . command_name ) ;
rb_gc_mark ( eargp - > invoke . cmd . command_abspath ) ;
rb_gc_mark ( eargp - > invoke . cmd . argv_str ) ;
rb_gc_mark ( eargp - > invoke . cmd . argv_buf ) ;
2012-06-20 14:31:02 +04:00
}
2012-06-23 03:09:16 +04:00
rb_gc_mark ( eargp - > redirect_fds ) ;
rb_gc_mark ( eargp - > envp_str ) ;
rb_gc_mark ( eargp - > envp_buf ) ;
rb_gc_mark ( eargp - > dup2_tmpbuf ) ;
2012-06-23 11:30:26 +04:00
rb_gc_mark ( eargp - > rlimit_limits ) ;
2012-06-23 15:35:32 +04:00
rb_gc_mark ( eargp - > fd_dup2 ) ;
rb_gc_mark ( eargp - > fd_close ) ;
rb_gc_mark ( eargp - > fd_open ) ;
rb_gc_mark ( eargp - > fd_dup2_child ) ;
2012-06-23 12:18:34 +04:00
rb_gc_mark ( eargp - > env_modification ) ;
2016-11-06 03:58:49 +03:00
rb_gc_mark ( eargp - > path_env ) ;
2012-06-23 10:23:35 +04:00
rb_gc_mark ( eargp - > chdir_dir ) ;
2012-06-20 14:31:02 +04:00
}
static size_t
memsize_exec_arg ( const void * ptr )
{
2014-09-13 09:14:51 +04:00
return sizeof ( struct rb_execarg ) ;
2012-06-20 14:31:02 +04:00
}
static const rb_data_type_t exec_arg_data_type = {
2013-06-30 05:57:16 +04:00
" exec_arg " ,
2014-09-13 09:14:51 +04:00
{ mark_exec_arg , RUBY_TYPED_DEFAULT_FREE , memsize_exec_arg } ,
2014-12-01 09:38:04 +03:00
0 , 0 , RUBY_TYPED_FREE_IMMEDIATELY
2012-06-20 14:31:02 +04:00
} ;
2013-06-30 05:59:21 +04:00
# ifdef _WIN32
# define DEFAULT_PROCESS_ENCODING rb_utf8_encoding()
# endif
2013-06-30 05:57:18 +04:00
# ifdef DEFAULT_PROCESS_ENCODING
# define EXPORT_STR(str) rb_str_export_to_enc((str), DEFAULT_PROCESS_ENCODING)
# define EXPORT_DUP(str) export_dup(str)
static VALUE
export_dup ( VALUE str )
{
VALUE newstr = EXPORT_STR ( str ) ;
if ( newstr = = str ) newstr = rb_str_dup ( str ) ;
return newstr ;
}
# else
# define EXPORT_STR(str) (str)
# define EXPORT_DUP(str) rb_str_dup(str)
# endif
2014-09-03 02:51:03 +04:00
# if !defined(HAVE_WORKING_FORK) && defined(HAVE_SPAWNV)
2011-08-19 09:25:52 +04:00
# define USE_SPAWNV 1
# else
# define USE_SPAWNV 0
# endif
# ifndef P_NOWAIT
# define P_NOWAIT _P_NOWAIT
# endif
# if USE_SPAWNV
2005-05-16 17:42:59 +04:00
# if defined(_WIN32)
2013-06-30 05:59:21 +04:00
# define proc_spawn_cmd_internal(argv, prog) rb_w32_uaspawn(P_NOWAIT, (prog), (argv))
2005-05-16 17:42:59 +04:00
# else
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
static rb_pid_t
2012-06-06 16:33:28 +04:00
proc_spawn_cmd_internal ( char * * argv , char * prog )
1998-01-16 15:19:22 +03:00
{
2008-05-08 01:43:54 +04:00
char fbuf [ MAXPATHLEN ] ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t status ;
1998-01-16 15:13:05 +03:00
2002-12-31 15:31:12 +03:00
if ( ! prog )
prog = argv [ 0 ] ;
2008-05-08 01:43:54 +04:00
prog = dln_find_exe_r ( prog , 0 , fbuf , sizeof ( fbuf ) ) ;
2002-12-31 15:31:12 +03:00
if ( ! prog )
return - 1 ;
1998-01-16 15:13:05 +03:00
before_exec ( ) ;
2011-08-19 09:25:52 +04:00
status = spawnv ( P_NOWAIT , prog , ( const char * * ) argv ) ;
if ( status = = - 1 & & errno = = ENOEXEC ) {
2010-11-05 06:18:03 +03:00
* argv = ( char * ) prog ;
* - - argv = ( char * ) " sh " ;
2011-08-19 09:25:52 +04:00
status = spawnv ( P_NOWAIT , " /bin/sh " , ( const char * * ) argv ) ;
2010-11-04 19:21:38 +03:00
after_exec ( ) ;
2011-08-19 09:25:52 +04:00
if ( status = = - 1 ) errno = ENOEXEC ;
}
2001-02-15 09:01:00 +03:00
return status ;
1998-01-16 15:13:05 +03:00
}
2005-05-16 17:42:59 +04:00
# endif
1998-01-16 15:13:05 +03:00
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
static rb_pid_t
2012-06-23 18:21:47 +04:00
proc_spawn_cmd ( char * * argv , VALUE prog , struct rb_execarg * eargp )
1998-01-16 15:13:05 +03:00
{
2011-01-27 02:41:47 +03:00
rb_pid_t pid = - 1 ;
1998-01-16 15:13:05 +03:00
2012-06-04 05:44:27 +04:00
if ( argv [ 0 ] ) {
2012-04-07 18:10:30 +04:00
# if defined(_WIN32)
DWORD flags = 0 ;
2012-06-23 18:21:47 +04:00
if ( eargp - > new_pgroup_given & & eargp - > new_pgroup_flag ) {
2012-04-07 18:10:30 +04:00
flags = CREATE_NEW_PROCESS_GROUP ;
}
2013-06-30 05:59:21 +04:00
pid = rb_w32_uaspawn_flags ( P_NOWAIT , prog ? RSTRING_PTR ( prog ) : 0 , argv , flags ) ;
2012-04-07 18:10:30 +04:00
# else
2012-06-06 16:33:28 +04:00
pid = proc_spawn_cmd_internal ( argv , prog ? RSTRING_PTR ( prog ) : 0 ) ;
2012-04-07 18:10:30 +04:00
# endif
}
2011-01-27 02:41:47 +03:00
return pid ;
1998-01-16 15:13:05 +03:00
}
2004-02-16 09:45:32 +03:00
# if defined(_WIN32)
2013-06-30 05:59:21 +04:00
# define proc_spawn_sh(str) rb_w32_uspawn(P_NOWAIT, (str), 0)
2004-02-16 09:45:32 +03:00
# else
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
static rb_pid_t
2012-06-06 16:33:28 +04:00
proc_spawn_sh ( char * str )
2004-02-16 09:45:32 +03:00
{
2008-05-08 01:43:54 +04:00
char fbuf [ MAXPATHLEN ] ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t status ;
2012-06-05 14:35:47 +04:00
char * shell = dln_find_exe_r ( " sh " , 0 , fbuf , sizeof ( fbuf ) ) ;
before_exec ( ) ;
status = spawnl ( P_NOWAIT , ( shell ? shell : " /bin/sh " ) , " sh " , " -c " , str , ( char * ) NULL ) ;
after_exec ( ) ;
2011-01-27 02:41:47 +03:00
return status ;
1998-01-16 15:13:05 +03:00
}
2002-12-31 15:31:12 +03:00
# endif
# endif
1998-01-16 15:13:05 +03:00
2008-04-24 18:46:39 +04:00
static VALUE
hide_obj ( VALUE obj )
{
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
RBASIC_CLEAR_CLASS ( obj ) ;
2008-04-24 18:46:39 +04:00
return obj ;
}
static VALUE
2011-03-07 11:44:45 +03:00
check_exec_redirect_fd ( VALUE v , int iskey )
2008-04-24 18:46:39 +04:00
{
VALUE tmp ;
int fd ;
if ( FIXNUM_P ( v ) ) {
fd = FIX2INT ( v ) ;
}
2008-12-03 18:02:10 +03:00
else if ( SYMBOL_P ( v ) ) {
2014-11-24 06:44:45 +03:00
ID id = rb_check_id ( & v ) ;
2014-11-24 06:44:24 +03:00
if ( id = = id_in )
2008-12-03 18:02:10 +03:00
fd = 0 ;
2014-11-24 06:44:24 +03:00
else if ( id = = id_out )
2008-12-03 18:02:10 +03:00
fd = 1 ;
2014-11-24 06:44:24 +03:00
else if ( id = = id_err )
2008-12-03 18:02:10 +03:00
fd = 2 ;
else
goto wrong ;
}
2019-11-04 03:14:18 +03:00
else if ( ! NIL_P ( tmp = rb_io_check_io ( v ) ) ) {
2008-04-24 18:46:39 +04:00
rb_io_t * fptr ;
GetOpenFile ( tmp , fptr ) ;
2008-04-30 09:40:19 +04:00
if ( fptr - > tied_io_for_writing )
rb_raise ( rb_eArgError , " duplex IO redirection " ) ;
2008-04-24 18:46:39 +04:00
fd = fptr - > fd ;
}
else {
2020-06-16 06:27:33 +03:00
goto wrong ;
2008-04-24 18:46:39 +04:00
}
if ( fd < 0 ) {
rb_raise ( rb_eArgError , " negative file descriptor " ) ;
}
2011-03-07 11:44:45 +03:00
# ifdef _WIN32
else if ( fd > = 3 & & iskey ) {
rb_raise ( rb_eArgError , " wrong file descriptor (%d) " , fd ) ;
}
# endif
2008-04-24 18:46:39 +04:00
return INT2FIX ( fd ) ;
2020-06-16 06:27:33 +03:00
wrong :
rb_raise ( rb_eArgError , " wrong exec redirect " ) ;
2020-06-24 10:23:59 +03:00
UNREACHABLE_RETURN ( Qundef ) ;
2008-04-24 18:46:39 +04:00
}
2012-06-23 13:44:43 +04:00
static VALUE
check_exec_redirect1 ( VALUE ary , VALUE key , VALUE param )
{
2012-06-23 15:35:32 +04:00
if ( ary = = Qfalse ) {
2012-06-23 13:44:43 +04:00
ary = hide_obj ( rb_ary_new ( ) ) ;
}
if ( ! RB_TYPE_P ( key , T_ARRAY ) ) {
VALUE fd = check_exec_redirect_fd ( key , ! NIL_P ( param ) ) ;
rb_ary_push ( ary , hide_obj ( rb_assoc_new ( fd , param ) ) ) ;
}
else {
2020-11-09 13:25:11 +03:00
int i ;
2012-06-23 13:44:43 +04:00
for ( i = 0 ; i < RARRAY_LEN ( key ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE v = RARRAY_AREF ( key , i ) ;
2012-06-23 13:44:43 +04:00
VALUE fd = check_exec_redirect_fd ( v , ! NIL_P ( param ) ) ;
rb_ary_push ( ary , hide_obj ( rb_assoc_new ( fd , param ) ) ) ;
}
}
return ary ;
}
2008-04-24 18:46:39 +04:00
static void
2012-06-23 15:35:32 +04:00
check_exec_redirect ( VALUE key , VALUE val , struct rb_execarg * eargp )
2008-04-24 18:46:39 +04:00
{
2012-06-23 15:35:32 +04:00
VALUE param ;
2008-04-24 18:46:39 +04:00
VALUE path , flags , perm ;
2012-07-27 13:25:54 +04:00
VALUE tmp ;
2008-04-24 18:46:39 +04:00
ID id ;
switch ( TYPE ( val ) ) {
case T_SYMBOL :
2020-06-16 06:53:24 +03:00
id = rb_check_id ( & val ) ;
2014-11-24 06:44:24 +03:00
if ( id = = id_close ) {
2008-04-24 18:46:39 +04:00
param = Qnil ;
2012-06-23 15:35:32 +04:00
eargp - > fd_close = check_exec_redirect1 ( eargp - > fd_close , key , param ) ;
2008-04-24 18:46:39 +04:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_in ) {
2008-12-03 15:33:37 +03:00
param = INT2FIX ( 0 ) ;
2012-06-23 15:35:32 +04:00
eargp - > fd_dup2 = check_exec_redirect1 ( eargp - > fd_dup2 , key , param ) ;
2008-12-03 15:33:37 +03:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_out ) {
2008-12-03 15:33:37 +03:00
param = INT2FIX ( 1 ) ;
2012-06-23 15:35:32 +04:00
eargp - > fd_dup2 = check_exec_redirect1 ( eargp - > fd_dup2 , key , param ) ;
2008-12-03 15:33:37 +03:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_err ) {
2008-12-03 15:33:37 +03:00
param = INT2FIX ( 2 ) ;
2012-06-23 15:35:32 +04:00
eargp - > fd_dup2 = check_exec_redirect1 ( eargp - > fd_dup2 , key , param ) ;
2008-12-03 15:33:37 +03:00
}
2008-04-24 18:46:39 +04:00
else {
2014-11-24 06:44:45 +03:00
rb_raise ( rb_eArgError , " wrong exec redirect symbol: % " PRIsVALUE ,
val ) ;
2008-04-24 18:46:39 +04:00
}
break ;
case T_FILE :
2012-07-27 13:25:54 +04:00
io :
2011-03-07 11:44:45 +03:00
val = check_exec_redirect_fd ( val , 0 ) ;
2008-04-24 18:46:39 +04:00
/* fall through */
case T_FIXNUM :
param = val ;
2012-06-23 15:35:32 +04:00
eargp - > fd_dup2 = check_exec_redirect1 ( eargp - > fd_dup2 , key , param ) ;
2008-04-24 18:46:39 +04:00
break ;
case T_ARRAY :
path = rb_ary_entry ( val , 0 ) ;
2008-12-03 18:02:10 +03:00
if ( RARRAY_LEN ( val ) = = 2 & & SYMBOL_P ( path ) & &
2014-11-24 06:44:45 +03:00
path = = ID2SYM ( id_child ) ) {
2011-03-07 11:44:45 +03:00
param = check_exec_redirect_fd ( rb_ary_entry ( val , 1 ) , 0 ) ;
2012-06-23 15:35:32 +04:00
eargp - > fd_dup2_child = check_exec_redirect1 ( eargp - > fd_dup2_child , key , param ) ;
2008-12-03 18:02:10 +03:00
}
else {
FilePathValue ( path ) ;
flags = rb_ary_entry ( val , 1 ) ;
if ( NIL_P ( flags ) )
flags = INT2NUM ( O_RDONLY ) ;
2011-09-29 15:07:45 +04:00
else if ( RB_TYPE_P ( flags , T_STRING ) )
2008-12-03 18:02:10 +03:00
flags = INT2NUM ( rb_io_modestr_oflags ( StringValueCStr ( flags ) ) ) ;
else
flags = rb_to_int ( flags ) ;
perm = rb_ary_entry ( val , 2 ) ;
perm = NIL_P ( perm ) ? INT2FIX ( 0644 ) : rb_to_int ( perm ) ;
2015-04-09 15:44:35 +03:00
param = hide_obj ( rb_ary_new3 ( 4 , hide_obj ( EXPORT_DUP ( path ) ) ,
flags , perm , Qnil ) ) ;
2012-06-23 15:35:32 +04:00
eargp - > fd_open = check_exec_redirect1 ( eargp - > fd_open , key , param ) ;
2008-12-03 18:02:10 +03:00
}
2008-04-24 18:46:39 +04:00
break ;
case T_STRING :
path = val ;
FilePathValue ( path ) ;
2011-09-29 15:07:45 +04:00
if ( RB_TYPE_P ( key , T_FILE ) )
2011-03-07 11:44:45 +03:00
key = check_exec_redirect_fd ( key , 1 ) ;
2008-09-30 19:21:30 +04:00
if ( FIXNUM_P ( key ) & & ( FIX2INT ( key ) = = 1 | | FIX2INT ( key ) = = 2 ) )
2008-04-24 18:46:39 +04:00
flags = INT2NUM ( O_WRONLY | O_CREAT | O_TRUNC ) ;
2014-06-15 05:09:17 +04:00
else if ( RB_TYPE_P ( key , T_ARRAY ) ) {
2014-05-05 17:37:09 +04:00
int i ;
for ( i = 0 ; i < RARRAY_LEN ( key ) ; i + + ) {
2018-10-10 07:20:21 +03:00
VALUE v = RARRAY_AREF ( key , i ) ;
2014-05-05 17:37:09 +04:00
VALUE fd = check_exec_redirect_fd ( v , 1 ) ;
if ( FIX2INT ( fd ) ! = 1 & & FIX2INT ( fd ) ! = 2 ) break ;
}
if ( i = = RARRAY_LEN ( key ) )
flags = INT2NUM ( O_WRONLY | O_CREAT | O_TRUNC ) ;
else
flags = INT2NUM ( O_RDONLY ) ;
}
else
2008-04-24 18:46:39 +04:00
flags = INT2NUM ( O_RDONLY ) ;
perm = INT2FIX ( 0644 ) ;
2015-04-09 15:44:35 +03:00
param = hide_obj ( rb_ary_new3 ( 4 , hide_obj ( EXPORT_DUP ( path ) ) ,
flags , perm , Qnil ) ) ;
2012-06-23 15:35:32 +04:00
eargp - > fd_open = check_exec_redirect1 ( eargp - > fd_open , key , param ) ;
2008-04-24 18:46:39 +04:00
break ;
default :
2012-07-27 13:25:54 +04:00
tmp = val ;
val = rb_io_check_io ( tmp ) ;
if ( ! NIL_P ( val ) ) goto io ;
2008-04-24 18:46:39 +04:00
rb_raise ( rb_eArgError , " wrong exec redirect action " ) ;
}
}
2011-03-07 11:44:45 +03:00
# if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
2017-07-13 23:47:36 +03:00
static int rlimit_type_by_sym ( VALUE key ) ;
static void
rb_execarg_addopt_rlimit ( struct rb_execarg * eargp , int rtype , VALUE val )
{
VALUE ary = eargp - > rlimit_limits ;
VALUE tmp , softlim , hardlim ;
if ( eargp - > rlimit_limits = = Qfalse )
ary = eargp - > rlimit_limits = hide_obj ( rb_ary_new ( ) ) ;
else
ary = eargp - > rlimit_limits ;
tmp = rb_check_array_type ( val ) ;
if ( ! NIL_P ( tmp ) ) {
if ( RARRAY_LEN ( tmp ) = = 1 )
softlim = hardlim = rb_to_int ( rb_ary_entry ( tmp , 0 ) ) ;
else if ( RARRAY_LEN ( tmp ) = = 2 ) {
softlim = rb_to_int ( rb_ary_entry ( tmp , 0 ) ) ;
hardlim = rb_to_int ( rb_ary_entry ( tmp , 1 ) ) ;
}
else {
rb_raise ( rb_eArgError , " wrong exec rlimit option " ) ;
}
}
else {
softlim = hardlim = rb_to_int ( val ) ;
}
tmp = hide_obj ( rb_ary_new3 ( 3 , INT2NUM ( rtype ) , softlim , hardlim ) ) ;
rb_ary_push ( ary , tmp ) ;
}
2008-04-24 18:46:39 +04:00
# endif
2019-07-16 15:38:25 +03:00
# define TO_BOOL(val, name) NIL_P(val) ? 0 : rb_bool_expected((val), name)
2008-04-28 04:11:46 +04:00
int
2012-06-21 16:18:40 +04:00
rb_execarg_addopt ( VALUE execarg_obj , VALUE key , VALUE val )
2008-04-24 18:46:39 +04:00
{
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
2012-06-21 16:18:40 +04:00
2008-04-24 18:46:39 +04:00
ID id ;
switch ( TYPE ( key ) ) {
case T_SYMBOL :
2017-07-13 23:47:36 +03:00
# if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
{
int rtype = rlimit_type_by_sym ( key ) ;
if ( rtype ! = - 1 ) {
rb_execarg_addopt_rlimit ( eargp , rtype , val ) ;
RB_GC_GUARD ( execarg_obj ) ;
return ST_CONTINUE ;
}
}
# endif
2014-11-24 06:44:45 +03:00
if ( ! ( id = rb_check_id ( & key ) ) ) return ST_STOP ;
2008-04-24 18:46:39 +04:00
# ifdef HAVE_SETPGID
2014-11-24 06:44:24 +03:00
if ( id = = id_pgroup ) {
2013-03-21 20:11:32 +04:00
rb_pid_t pgroup ;
2012-06-23 03:09:16 +04:00
if ( eargp - > pgroup_given ) {
2008-04-24 18:46:39 +04:00
rb_raise ( rb_eArgError , " pgroup option specified twice " ) ;
}
if ( ! RTEST ( val ) )
2012-06-22 15:30:29 +04:00
pgroup = - 1 ; /* asis(-1) means "don't call setpgid()". */
2008-04-24 18:46:39 +04:00
else if ( val = = Qtrue )
2012-06-22 15:30:29 +04:00
pgroup = 0 ; /* new process group. */
2008-04-24 18:46:39 +04:00
else {
2012-06-22 15:30:29 +04:00
pgroup = NUM2PIDT ( val ) ;
2008-04-24 18:46:39 +04:00
if ( pgroup < 0 ) {
rb_raise ( rb_eArgError , " negative process group ID : %ld " , ( long ) pgroup ) ;
}
}
2012-06-23 03:09:16 +04:00
eargp - > pgroup_given = 1 ;
eargp - > pgroup_pgid = pgroup ;
2008-04-24 18:46:39 +04:00
}
else
# endif
2012-04-07 18:10:30 +04:00
# ifdef _WIN32
2014-11-24 06:44:24 +03:00
if ( id = = id_new_pgroup ) {
2012-06-23 18:21:47 +04:00
if ( eargp - > new_pgroup_given ) {
2012-04-07 18:10:30 +04:00
rb_raise ( rb_eArgError , " new_pgroup option specified twice " ) ;
}
2012-06-23 18:21:47 +04:00
eargp - > new_pgroup_given = 1 ;
2019-07-16 15:38:25 +03:00
eargp - > new_pgroup_flag = TO_BOOL ( val , " new_pgroup " ) ;
2012-04-07 18:10:30 +04:00
}
else
2008-04-24 18:46:39 +04:00
# endif
2014-11-24 06:44:24 +03:00
if ( id = = id_unsetenv_others ) {
2012-06-23 05:43:51 +04:00
if ( eargp - > unsetenv_others_given ) {
2008-04-24 18:46:39 +04:00
rb_raise ( rb_eArgError , " unsetenv_others option specified twice " ) ;
}
2012-06-23 05:43:51 +04:00
eargp - > unsetenv_others_given = 1 ;
2019-07-16 15:38:25 +03:00
eargp - > unsetenv_others_do = TO_BOOL ( val , " unsetenv_others " ) ;
2008-04-24 18:46:39 +04:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_chdir ) {
2012-06-23 10:23:35 +04:00
if ( eargp - > chdir_given ) {
2008-04-24 18:46:39 +04:00
rb_raise ( rb_eArgError , " chdir option specified twice " ) ;
}
FilePathValue ( val ) ;
2015-12-27 15:03:45 +03:00
val = rb_str_encode_ospath ( val ) ;
2012-06-23 10:23:35 +04:00
eargp - > chdir_given = 1 ;
2013-06-30 05:57:18 +04:00
eargp - > chdir_dir = hide_obj ( EXPORT_DUP ( val ) ) ;
2008-04-24 18:46:39 +04:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_umask ) {
2011-01-28 05:00:08 +03:00
mode_t cmask = NUM2MODET ( val ) ;
2012-06-23 03:09:16 +04:00
if ( eargp - > umask_given ) {
2008-04-24 18:46:39 +04:00
rb_raise ( rb_eArgError , " umask option specified twice " ) ;
}
2012-06-23 03:09:16 +04:00
eargp - > umask_given = 1 ;
eargp - > umask_mask = cmask ;
2008-04-24 18:46:39 +04:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_close_others ) {
2012-06-23 08:23:03 +04:00
if ( eargp - > close_others_given ) {
2008-04-24 18:46:39 +04:00
rb_raise ( rb_eArgError , " close_others option specified twice " ) ;
}
2012-06-23 08:23:03 +04:00
eargp - > close_others_given = 1 ;
2019-07-16 15:38:25 +03:00
eargp - > close_others_do = TO_BOOL ( val , " close_others " ) ;
2008-04-24 18:46:39 +04:00
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_in ) {
2008-04-24 18:46:39 +04:00
key = INT2FIX ( 0 ) ;
goto redirect ;
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_out ) {
2008-04-24 18:46:39 +04:00
key = INT2FIX ( 1 ) ;
goto redirect ;
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_err ) {
2008-04-24 18:46:39 +04:00
key = INT2FIX ( 2 ) ;
goto redirect ;
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_uid ) {
2012-10-09 12:13:29 +04:00
# ifdef HAVE_SETUID
if ( eargp - > uid_given ) {
rb_raise ( rb_eArgError , " uid option specified twice " ) ;
}
check_uid_switch ( ) ;
{
eargp - > uid = OBJ2UID ( val ) ;
eargp - > uid_given = 1 ;
}
# else
rb_raise ( rb_eNotImpError ,
" uid option is unimplemented on this machine " ) ;
# endif
}
2014-11-24 06:44:24 +03:00
else if ( id = = id_gid ) {
2012-10-09 12:13:29 +04:00
# ifdef HAVE_SETGID
if ( eargp - > gid_given ) {
rb_raise ( rb_eArgError , " gid option specified twice " ) ;
}
check_gid_switch ( ) ;
{
eargp - > gid = OBJ2GID ( val ) ;
eargp - > gid_given = 1 ;
}
# else
rb_raise ( rb_eNotImpError ,
" gid option is unimplemented on this machine " ) ;
# endif
}
2019-07-16 12:47:35 +03:00
else if ( id = = id_exception ) {
if ( eargp - > exception_given ) {
rb_raise ( rb_eArgError , " exception option specified twice " ) ;
}
eargp - > exception_given = 1 ;
2019-07-16 15:38:25 +03:00
eargp - > exception = TO_BOOL ( val , " exception " ) ;
2019-07-16 12:47:35 +03:00
}
2008-04-24 18:46:39 +04:00
else {
2012-06-27 04:15:51 +04:00
return ST_STOP ;
2008-04-24 18:46:39 +04:00
}
break ;
case T_FIXNUM :
case T_FILE :
case T_ARRAY :
redirect :
2012-06-23 15:35:32 +04:00
check_exec_redirect ( key , val , eargp ) ;
2008-04-24 18:46:39 +04:00
break ;
default :
2012-06-27 04:15:51 +04:00
return ST_STOP ;
2008-04-24 18:46:39 +04:00
}
2012-06-21 16:18:40 +04:00
RB_GC_GUARD ( execarg_obj ) ;
2008-04-24 18:46:39 +04:00
return ST_CONTINUE ;
}
2008-04-28 04:11:46 +04:00
static int
check_exec_options_i ( st_data_t st_key , st_data_t st_val , st_data_t arg )
{
VALUE key = ( VALUE ) st_key ;
VALUE val = ( VALUE ) st_val ;
2012-06-21 15:36:25 +04:00
VALUE execarg_obj = ( VALUE ) arg ;
2012-06-27 04:15:51 +04:00
if ( rb_execarg_addopt ( execarg_obj , key , val ) ! = ST_CONTINUE ) {
if ( SYMBOL_P ( key ) )
2017-07-14 07:43:16 +03:00
rb_raise ( rb_eArgError , " wrong exec option symbol: % " PRIsVALUE ,
2012-06-27 04:15:51 +04:00
key ) ;
rb_raise ( rb_eArgError , " wrong exec option " ) ;
}
return ST_CONTINUE ;
}
static int
check_exec_options_i_extract ( st_data_t st_key , st_data_t st_val , st_data_t arg )
{
VALUE key = ( VALUE ) st_key ;
VALUE val = ( VALUE ) st_val ;
VALUE * args = ( VALUE * ) arg ;
VALUE execarg_obj = args [ 0 ] ;
if ( rb_execarg_addopt ( execarg_obj , key , val ) ! = ST_CONTINUE ) {
VALUE nonopts = args [ 1 ] ;
if ( NIL_P ( nonopts ) ) args [ 1 ] = nonopts = rb_hash_new ( ) ;
rb_hash_aset ( nonopts , key , val ) ;
}
return ST_CONTINUE ;
2008-04-28 04:11:46 +04:00
}
2012-06-24 17:53:44 +04:00
static int
check_exec_fds_1 ( struct rb_execarg * eargp , VALUE h , int maxhint , VALUE ary )
2008-04-24 18:46:39 +04:00
{
2011-03-08 03:08:16 +03:00
long i ;
2012-06-24 17:53:44 +04:00
if ( ary ! = Qfalse ) {
2008-04-24 18:46:39 +04:00
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE elt = RARRAY_AREF ( ary , i ) ;
int fd = FIX2INT ( RARRAY_AREF ( elt , 0 ) ) ;
2008-04-24 18:46:39 +04:00
if ( RTEST ( rb_hash_lookup ( h , INT2FIX ( fd ) ) ) ) {
rb_raise ( rb_eArgError , " fd %d specified twice " , fd ) ;
}
2015-04-09 15:44:35 +03:00
if ( ary = = eargp - > fd_dup2 )
2008-12-04 13:17:34 +03:00
rb_hash_aset ( h , INT2FIX ( fd ) , Qtrue ) ;
2012-06-23 15:35:32 +04:00
else if ( ary = = eargp - > fd_dup2_child )
2013-05-13 13:56:22 +04:00
rb_hash_aset ( h , INT2FIX ( fd ) , RARRAY_AREF ( elt , 1 ) ) ;
2012-06-23 15:35:32 +04:00
else /* ary == eargp->fd_close */
2008-12-04 13:17:34 +03:00
rb_hash_aset ( h , INT2FIX ( fd ) , INT2FIX ( - 1 ) ) ;
2008-04-24 18:46:39 +04:00
if ( maxhint < fd )
maxhint = fd ;
2012-06-23 15:35:32 +04:00
if ( ary = = eargp - > fd_dup2 | | ary = = eargp - > fd_dup2_child ) {
2013-05-13 13:56:22 +04:00
fd = FIX2INT ( RARRAY_AREF ( elt , 1 ) ) ;
2008-04-24 18:46:39 +04:00
if ( maxhint < fd )
maxhint = fd ;
}
}
}
2012-06-24 17:53:44 +04:00
return maxhint ;
}
static VALUE
check_exec_fds ( struct rb_execarg * eargp )
{
VALUE h = rb_hash_new ( ) ;
VALUE ary ;
int maxhint = - 1 ;
long i ;
maxhint = check_exec_fds_1 ( eargp , h , maxhint , eargp - > fd_dup2 ) ;
maxhint = check_exec_fds_1 ( eargp , h , maxhint , eargp - > fd_close ) ;
maxhint = check_exec_fds_1 ( eargp , h , maxhint , eargp - > fd_dup2_child ) ;
2008-12-03 18:02:10 +03:00
2012-06-23 15:35:32 +04:00
if ( eargp - > fd_dup2_child ) {
ary = eargp - > fd_dup2_child ;
2008-12-03 18:02:10 +03:00
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE elt = RARRAY_AREF ( ary , i ) ;
int newfd = FIX2INT ( RARRAY_AREF ( elt , 0 ) ) ;
int oldfd = FIX2INT ( RARRAY_AREF ( elt , 1 ) ) ;
2008-12-04 13:17:34 +03:00
int lastfd = oldfd ;
VALUE val = rb_hash_lookup ( h , INT2FIX ( lastfd ) ) ;
long depth = 0 ;
while ( FIXNUM_P ( val ) & & 0 < = FIX2INT ( val ) ) {
lastfd = FIX2INT ( val ) ;
val = rb_hash_lookup ( h , val ) ;
if ( RARRAY_LEN ( ary ) < depth )
rb_raise ( rb_eArgError , " cyclic child fd redirection from %d " , oldfd ) ;
depth + + ;
}
if ( val ! = Qtrue )
2008-12-03 18:02:10 +03:00
rb_raise ( rb_eArgError , " child fd %d is not redirected " , oldfd ) ;
2008-12-04 13:17:34 +03:00
if ( oldfd ! = lastfd ) {
VALUE val2 ;
rb_ary_store ( elt , 1 , INT2FIX ( lastfd ) ) ;
rb_hash_aset ( h , INT2FIX ( newfd ) , INT2FIX ( lastfd ) ) ;
val = INT2FIX ( oldfd ) ;
while ( FIXNUM_P ( val2 = rb_hash_lookup ( h , val ) ) ) {
rb_hash_aset ( h , val , INT2FIX ( lastfd ) ) ;
val = val2 ;
}
2008-12-03 18:02:10 +03:00
}
}
}
2012-06-23 08:23:03 +04:00
eargp - > close_others_maxhint = maxhint ;
2008-04-24 18:46:39 +04:00
return h ;
}
2008-04-28 04:11:46 +04:00
static void
2012-06-21 15:36:25 +04:00
rb_check_exec_options ( VALUE opthash , VALUE execarg_obj )
2008-04-24 18:46:39 +04:00
{
2008-04-28 04:11:46 +04:00
if ( RHASH_EMPTY_P ( opthash ) )
return ;
2018-10-31 01:11:51 +03:00
rb_hash_stlike_foreach ( opthash , check_exec_options_i , ( st_data_t ) execarg_obj ) ;
2008-04-24 18:46:39 +04:00
}
2012-06-27 04:15:51 +04:00
VALUE
rb_execarg_extract_options ( VALUE execarg_obj , VALUE opthash )
{
VALUE args [ 2 ] ;
if ( RHASH_EMPTY_P ( opthash ) )
return Qnil ;
args [ 0 ] = execarg_obj ;
args [ 1 ] = Qnil ;
2018-10-31 01:11:51 +03:00
rb_hash_stlike_foreach ( opthash , check_exec_options_i_extract , ( st_data_t ) args ) ;
2012-06-27 04:15:51 +04:00
return args [ 1 ] ;
}
2016-11-06 03:58:49 +03:00
# ifdef ENV_IGNORECASE
# define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
# else
# define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
# endif
2008-04-24 18:46:39 +04:00
static int
check_exec_env_i ( st_data_t st_key , st_data_t st_val , st_data_t arg )
{
VALUE key = ( VALUE ) st_key ;
VALUE val = ( VALUE ) st_val ;
2016-11-06 03:58:49 +03:00
VALUE env = ( ( VALUE * ) arg ) [ 0 ] ;
VALUE * path = & ( ( VALUE * ) arg ) [ 1 ] ;
2008-04-24 18:46:39 +04:00
char * k ;
k = StringValueCStr ( key ) ;
if ( strchr ( k , ' = ' ) )
2020-04-16 14:40:19 +03:00
rb_raise ( rb_eArgError , " environment name contains a equal : % " PRIsVALUE , key ) ;
2008-04-24 18:46:39 +04:00
if ( ! NIL_P ( val ) )
StringValueCStr ( val ) ;
2013-06-30 05:57:18 +04:00
key = EXPORT_STR ( key ) ;
if ( ! NIL_P ( val ) ) val = EXPORT_STR ( val ) ;
2016-11-06 03:58:49 +03:00
if ( ENVMATCH ( k , PATH_ENV ) ) {
* path = val ;
}
2008-04-24 18:46:39 +04:00
rb_ary_push ( env , hide_obj ( rb_assoc_new ( key , val ) ) ) ;
return ST_CONTINUE ;
}
static VALUE
2016-11-06 03:58:49 +03:00
rb_check_exec_env ( VALUE hash , VALUE * path )
2008-04-24 18:46:39 +04:00
{
2016-11-06 03:58:49 +03:00
VALUE env [ 2 ] ;
2008-04-24 18:46:39 +04:00
2016-11-06 03:58:49 +03:00
env [ 0 ] = hide_obj ( rb_ary_new ( ) ) ;
env [ 1 ] = Qfalse ;
2018-10-31 01:11:51 +03:00
rb_hash_stlike_foreach ( hash , check_exec_env_i , ( st_data_t ) env ) ;
2016-11-06 03:58:49 +03:00
* path = env [ 1 ] ;
2008-04-24 18:46:39 +04:00
2016-11-06 03:58:49 +03:00
return env [ 0 ] ;
2008-04-24 18:46:39 +04:00
}
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_check_argv ( int argc , VALUE * argv )
2004-02-16 09:45:32 +03:00
{
VALUE tmp , prog ;
int i ;
2012-03-15 01:10:34 +04:00
rb_check_arity ( argc , 1 , UNLIMITED_ARGUMENTS ) ;
2004-02-16 09:45:32 +03:00
prog = 0 ;
tmp = rb_check_array_type ( argv [ 0 ] ) ;
if ( ! NIL_P ( tmp ) ) {
2006-09-02 18:42:08 +04:00
if ( RARRAY_LEN ( tmp ) ! = 2 ) {
2004-02-16 09:45:32 +03:00
rb_raise ( rb_eArgError , " wrong first argument " ) ;
}
2013-05-13 13:56:22 +04:00
prog = RARRAY_AREF ( tmp , 0 ) ;
argv [ 0 ] = RARRAY_AREF ( tmp , 1 ) ;
2004-10-01 19:56:05 +04:00
SafeStringValue ( prog ) ;
2006-09-04 11:40:46 +04:00
StringValueCStr ( prog ) ;
2012-06-03 16:18:45 +04:00
prog = rb_str_new_frozen ( prog ) ;
2004-02-16 09:45:32 +03:00
}
for ( i = 0 ; i < argc ; i + + ) {
SafeStringValue ( argv [ i ] ) ;
2012-06-03 16:18:45 +04:00
argv [ i ] = rb_str_new_frozen ( argv [ i ] ) ;
2006-09-04 11:40:46 +04:00
StringValueCStr ( argv [ i ] ) ;
2004-02-16 09:45:32 +03:00
}
return prog ;
}
2016-05-07 01:58:03 +03:00
static VALUE
check_hash ( VALUE obj )
{
if ( RB_SPECIAL_CONST_P ( obj ) ) return Qnil ;
switch ( RB_BUILTIN_TYPE ( obj ) ) {
case T_STRING :
case T_ARRAY :
return Qnil ;
2020-04-08 09:13:37 +03:00
default :
break ;
2016-05-07 01:58:03 +03:00
}
return rb_check_hash_type ( obj ) ;
}
2008-04-28 04:11:46 +04:00
static VALUE
2012-06-03 16:25:54 +04:00
rb_exec_getargs ( int * argc_p , VALUE * * argv_p , int accept_shell , VALUE * env_ret , VALUE * opthash_ret )
2008-04-24 18:46:39 +04:00
{
VALUE hash , prog ;
if ( 0 < * argc_p ) {
2016-05-07 01:58:03 +03:00
hash = check_hash ( ( * argv_p ) [ * argc_p - 1 ] ) ;
2008-04-24 18:46:39 +04:00
if ( ! NIL_P ( hash ) ) {
2008-04-28 04:11:46 +04:00
* opthash_ret = hash ;
2008-04-24 18:46:39 +04:00
( * argc_p ) - - ;
}
}
if ( 0 < * argc_p ) {
2016-05-07 01:58:03 +03:00
hash = check_hash ( ( * argv_p ) [ 0 ] ) ;
2008-04-24 18:46:39 +04:00
if ( ! NIL_P ( hash ) ) {
* env_ret = hash ;
( * argc_p ) - - ;
( * argv_p ) + + ;
}
}
prog = rb_check_argv ( * argc_p , * argv_p ) ;
if ( ! prog ) {
prog = ( * argv_p ) [ 0 ] ;
if ( accept_shell & & * argc_p = = 1 ) {
* argc_p = 0 ;
* argv_p = 0 ;
}
}
return prog ;
}
2012-06-13 11:38:06 +04:00
# ifndef _WIN32
2012-06-13 04:56:31 +04:00
struct string_part {
const char * ptr ;
size_t len ;
} ;
static int
compare_posix_sh ( const void * key , const void * el )
{
const struct string_part * word = key ;
int ret = strncmp ( word - > ptr , el , word - > len ) ;
if ( ! ret & & ( ( const char * ) el ) [ word - > len ] ) ret = - 1 ;
return ret ;
}
2012-06-13 11:38:06 +04:00
# endif
2012-06-13 04:56:31 +04:00
2008-04-28 04:11:46 +04:00
static void
2012-06-21 14:03:23 +04:00
rb_exec_fillarg ( VALUE prog , int argc , VALUE * argv , VALUE env , VALUE opthash , VALUE execarg_obj )
2008-04-24 18:46:39 +04:00
{
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
2012-06-06 15:49:30 +04:00
char fbuf [ MAXPATHLEN ] ;
2012-06-23 03:09:16 +04:00
MEMZERO ( eargp , struct rb_execarg , 1 ) ;
2008-04-24 18:46:39 +04:00
if ( ! NIL_P ( opthash ) ) {
2012-06-21 15:36:25 +04:00
rb_check_exec_options ( opthash , execarg_obj ) ;
2008-04-24 18:46:39 +04:00
}
if ( ! NIL_P ( env ) ) {
2016-11-06 03:58:49 +03:00
env = rb_check_exec_env ( env , & eargp - > path_env ) ;
2012-06-23 12:18:34 +04:00
eargp - > env_modification = env ;
2008-04-24 18:46:39 +04:00
}
2013-06-30 05:57:18 +04:00
prog = EXPORT_STR ( prog ) ;
2012-06-23 03:09:16 +04:00
eargp - > use_shell = argc = = 0 ;
if ( eargp - > use_shell )
eargp - > invoke . sh . shell_script = prog ;
2012-06-05 18:53:31 +04:00
else
2012-06-23 03:09:16 +04:00
eargp - > invoke . cmd . command_name = prog ;
2012-06-03 18:53:13 +04:00
# ifndef _WIN32
2012-06-23 03:09:16 +04:00
if ( eargp - > use_shell ) {
2012-06-13 05:20:05 +04:00
static const char posix_sh_cmds [ ] [ 9 ] = {
2012-06-13 04:56:31 +04:00
" ! " , /* reserved */
" . " , /* special built-in */
2012-10-12 15:41:40 +04:00
" : " , /* special built-in */
2012-06-13 04:56:31 +04:00
" break " , /* special built-in */
" case " , /* reserved */
" continue " , /* special built-in */
" do " , /* reserved */
" done " , /* reserved */
" elif " , /* reserved */
" else " , /* reserved */
" esac " , /* reserved */
" eval " , /* special built-in */
" exec " , /* special built-in */
" exit " , /* special built-in */
" export " , /* special built-in */
" fi " , /* reserved */
" for " , /* reserved */
" if " , /* reserved */
" in " , /* reserved */
" readonly " , /* special built-in */
" return " , /* special built-in */
" set " , /* special built-in */
" shift " , /* special built-in */
" then " , /* reserved */
" times " , /* special built-in */
" trap " , /* special built-in */
" unset " , /* special built-in */
" until " , /* reserved */
" while " , /* reserved */
} ;
2012-06-13 04:54:32 +04:00
const char * p ;
2012-06-13 04:56:31 +04:00
struct string_part first = { 0 , 0 } ;
2012-06-03 18:53:13 +04:00
int has_meta = 0 ;
2012-06-11 16:37:55 +04:00
/*
* meta characters :
*
* * Pathname Expansion
* ? Pathname Expansion
* { } Grouping Commands
* [ ] Pathname Expansion
* < > Redirection
* ( ) Grouping Commands
* ~ Tilde Expansion
* & AND Lists , Asynchronous Lists
* | OR Lists , Pipelines
* \ Escape Character
* $ Parameter Expansion
* ; Sequential Lists
* ' Single - Quotes
* ` Command Substitution
* " Double-Quotes
* \ n Lists
*
* # Comment
* = Assignment preceding command name
* % ( used in Parameter Expansion )
*/
2012-06-03 18:53:13 +04:00
for ( p = RSTRING_PTR ( prog ) ; * p ; p + + ) {
2012-06-13 04:56:31 +04:00
if ( * p = = ' ' | | * p = = ' \t ' ) {
if ( first . ptr & & ! first . len ) first . len = p - first . ptr ;
}
else {
if ( ! first . ptr ) first . ptr = p ;
}
2012-06-13 04:55:31 +04:00
if ( ! has_meta & & strchr ( " *?{}[]<>()~&| \\ $;'` \" \n # " , * p ) )
2012-06-03 18:53:13 +04:00
has_meta = 1 ;
2012-06-13 04:56:31 +04:00
if ( ! first . len ) {
if ( * p = = ' = ' ) {
has_meta = 1 ;
}
else if ( * p = = ' / ' ) {
2012-06-13 05:20:29 +04:00
first . len = 0x100 ; /* longer than any posix_sh_cmds */
2012-06-13 04:56:31 +04:00
}
}
if ( has_meta )
2012-06-05 14:21:22 +04:00
break ;
2012-06-03 18:53:13 +04:00
}
2012-06-13 04:56:31 +04:00
if ( ! has_meta & & first . ptr ) {
if ( ! first . len ) first . len = p - first . ptr ;
if ( first . len > 0 & & first . len < = sizeof ( posix_sh_cmds [ 0 ] ) & &
bsearch ( & first , posix_sh_cmds , numberof ( posix_sh_cmds ) , sizeof ( posix_sh_cmds [ 0 ] ) , compare_posix_sh ) )
has_meta = 1 ;
}
if ( ! has_meta ) {
2013-05-19 07:10:21 +04:00
/* avoid shell since no shell meta character found. */
2012-06-23 03:09:16 +04:00
eargp - > use_shell = 0 ;
2012-06-03 18:53:13 +04:00
}
2012-06-23 03:09:16 +04:00
if ( ! eargp - > use_shell ) {
2012-06-03 18:53:13 +04:00
VALUE argv_buf ;
argv_buf = hide_obj ( rb_str_buf_new ( 0 ) ) ;
p = RSTRING_PTR ( prog ) ;
while ( * p ) {
while ( * p = = ' ' | | * p = = ' \t ' )
p + + ;
if ( * p ) {
2012-06-13 04:54:32 +04:00
const char * w = p ;
2012-06-03 18:53:13 +04:00
while ( * p & & * p ! = ' ' & & * p ! = ' \t ' )
p + + ;
rb_str_buf_cat ( argv_buf , w , p - w ) ;
rb_str_buf_cat ( argv_buf , " " , 1 ) ; /* append '\0' */
}
}
2012-06-23 03:09:16 +04:00
eargp - > invoke . cmd . argv_buf = argv_buf ;
2018-02-03 06:50:28 +03:00
eargp - > invoke . cmd . command_name =
hide_obj ( rb_str_subseq ( argv_buf , 0 , strlen ( RSTRING_PTR ( argv_buf ) ) ) ) ;
rb_enc_copy ( eargp - > invoke . cmd . command_name , prog ) ;
2012-06-03 18:53:13 +04:00
}
}
# endif
2012-06-23 03:09:16 +04:00
if ( ! eargp - > use_shell ) {
2012-06-13 04:54:32 +04:00
const char * abspath ;
2016-11-06 03:58:49 +03:00
const char * path_env = 0 ;
if ( RTEST ( eargp - > path_env ) ) path_env = RSTRING_PTR ( eargp - > path_env ) ;
abspath = dln_find_exe_r ( RSTRING_PTR ( eargp - > invoke . cmd . command_name ) ,
path_env , fbuf , sizeof ( fbuf ) ) ;
2012-06-06 15:49:30 +04:00
if ( abspath )
2012-06-23 03:09:16 +04:00
eargp - > invoke . cmd . command_abspath = rb_str_new_cstr ( abspath ) ;
2012-06-06 15:49:30 +04:00
else
2012-06-23 03:09:16 +04:00
eargp - > invoke . cmd . command_abspath = Qnil ;
2012-06-06 15:49:30 +04:00
}
2012-06-23 03:09:16 +04:00
if ( ! eargp - > use_shell & & ! eargp - > invoke . cmd . argv_buf ) {
2012-06-03 18:53:13 +04:00
int i ;
VALUE argv_buf ;
argv_buf = rb_str_buf_new ( 0 ) ;
hide_obj ( argv_buf ) ;
for ( i = 0 ; i < argc ; i + + ) {
2013-06-30 05:57:18 +04:00
VALUE arg = argv [ i ] ;
const char * s = StringValueCStr ( arg ) ;
# ifdef DEFAULT_PROCESS_ENCODING
2013-06-30 18:16:26 +04:00
arg = EXPORT_STR ( arg ) ;
2013-06-30 05:57:18 +04:00
s = RSTRING_PTR ( arg ) ;
# endif
rb_str_buf_cat ( argv_buf , s , RSTRING_LEN ( arg ) + 1 ) ; /* include '\0' */
2012-06-03 18:53:13 +04:00
}
2012-06-23 03:09:16 +04:00
eargp - > invoke . cmd . argv_buf = argv_buf ;
2012-06-03 18:53:13 +04:00
}
2012-06-23 03:09:16 +04:00
if ( ! eargp - > use_shell ) {
2012-06-13 04:54:32 +04:00
const char * p , * ep , * null = NULL ;
2012-06-03 18:53:13 +04:00
VALUE argv_str ;
2012-06-04 15:01:41 +04:00
argv_str = hide_obj ( rb_str_buf_new ( sizeof ( char * ) * ( argc + 2 ) ) ) ;
rb_str_buf_cat ( argv_str , ( char * ) & null , sizeof ( null ) ) ; /* place holder for /bin/sh of try_with_sh. */
2012-06-23 03:09:16 +04:00
p = RSTRING_PTR ( eargp - > invoke . cmd . argv_buf ) ;
ep = p + RSTRING_LEN ( eargp - > invoke . cmd . argv_buf ) ;
2012-06-03 18:53:13 +04:00
while ( p < ep ) {
rb_str_buf_cat ( argv_str , ( char * ) & p , sizeof ( p ) ) ;
p + = strlen ( p ) + 1 ;
}
2012-06-04 15:01:41 +04:00
rb_str_buf_cat ( argv_str , ( char * ) & null , sizeof ( null ) ) ; /* terminator for execve. */
2018-05-14 06:30:03 +03:00
eargp - > invoke . cmd . argv_str =
rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString ( argv_str ) ;
2012-06-03 18:53:13 +04:00
}
2012-06-21 14:03:23 +04:00
RB_GC_GUARD ( execarg_obj ) ;
2008-04-24 18:46:39 +04:00
}
2013-06-04 12:23:26 +04:00
struct rb_execarg *
rb_execarg_get ( VALUE execarg_obj )
2012-06-20 14:31:02 +04:00
{
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp ;
TypedData_Get_Struct ( execarg_obj , struct rb_execarg , & exec_arg_data_type , eargp ) ;
return eargp ;
2012-06-20 14:31:02 +04:00
}
2018-12-03 12:15:16 +03:00
static VALUE
2019-07-16 12:47:35 +03:00
rb_execarg_init ( int argc , const VALUE * orig_argv , int accept_shell , VALUE execarg_obj )
2008-04-24 18:46:39 +04:00
{
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
2019-07-16 12:47:35 +03:00
VALUE prog , ret ;
2008-04-28 04:11:46 +04:00
VALUE env = Qnil , opthash = Qnil ;
2014-03-17 12:21:47 +04:00
VALUE argv_buf ;
VALUE * argv = ALLOCV_N ( VALUE , argv_buf , argc ) ;
MEMCPY ( argv , orig_argv , VALUE , argc ) ;
2012-06-03 16:25:54 +04:00
prog = rb_exec_getargs ( & argc , & argv , accept_shell , & env , & opthash ) ;
2012-06-21 14:03:23 +04:00
rb_exec_fillarg ( prog , argc , argv , env , opthash , execarg_obj ) ;
2014-03-17 12:21:47 +04:00
ALLOCV_END ( argv_buf ) ;
2012-06-23 03:09:16 +04:00
ret = eargp - > use_shell ? eargp - > invoke . sh . shell_script : eargp - > invoke . cmd . command_name ;
2012-06-21 13:39:10 +04:00
RB_GC_GUARD ( execarg_obj ) ;
return ret ;
2008-04-24 18:46:39 +04:00
}
2018-12-03 12:15:16 +03:00
VALUE
rb_execarg_new ( int argc , const VALUE * argv , int accept_shell , int allow_exc_opt )
{
VALUE execarg_obj ;
struct rb_execarg * eargp ;
execarg_obj = TypedData_Make_Struct ( 0 , struct rb_execarg , & exec_arg_data_type , eargp ) ;
2019-07-16 12:47:35 +03:00
rb_execarg_init ( argc , argv , accept_shell , execarg_obj ) ;
if ( ! allow_exc_opt & & eargp - > exception_given ) {
rb_raise ( rb_eArgError , " exception option is not allowed " ) ;
}
2018-12-03 12:15:16 +03:00
return execarg_obj ;
}
2012-06-27 04:15:51 +04:00
void
rb_execarg_setenv ( VALUE execarg_obj , VALUE env )
{
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
2016-11-06 03:58:49 +03:00
env = ! NIL_P ( env ) ? rb_check_exec_env ( env , & eargp - > path_env ) : Qfalse ;
2012-06-27 04:15:51 +04:00
eargp - > env_modification = env ;
}
2012-06-03 12:29:48 +04:00
static int
fill_envp_buf_i ( st_data_t st_key , st_data_t st_val , st_data_t arg )
{
VALUE key = ( VALUE ) st_key ;
VALUE val = ( VALUE ) st_val ;
VALUE envp_buf = ( VALUE ) arg ;
rb_str_buf_cat2 ( envp_buf , StringValueCStr ( key ) ) ;
rb_str_buf_cat2 ( envp_buf , " = " ) ;
rb_str_buf_cat2 ( envp_buf , StringValueCStr ( val ) ) ;
rb_str_buf_cat ( envp_buf , " " , 1 ) ; /* append '\0' */
return ST_CONTINUE ;
}
2012-06-05 16:59:40 +04:00
static long run_exec_dup2_tmpbuf_size ( long n ) ;
2015-04-09 19:33:02 +03:00
struct open_struct {
VALUE fname ;
int oflags ;
mode_t perm ;
int ret ;
int err ;
} ;
static void *
open_func ( void * ptr )
{
struct open_struct * data = ptr ;
const char * fname = RSTRING_PTR ( data - > fname ) ;
data - > ret = parent_redirect_open ( fname , data - > oflags , data - > perm ) ;
2015-04-10 12:45:29 +03:00
data - > err = errno ;
2015-04-09 19:33:02 +03:00
return NULL ;
}
2018-05-09 10:46:11 +03:00
static void
rb_execarg_allocate_dup2_tmpbuf ( struct rb_execarg * eargp , long len )
{
2019-10-04 20:08:07 +03:00
VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer ( ) ;
rb_imemo_tmpbuf_set_ptr ( tmpbuf , ruby_xmalloc ( run_exec_dup2_tmpbuf_size ( len ) ) ) ;
2018-05-09 20:40:04 +03:00
eargp - > dup2_tmpbuf = tmpbuf ;
2018-05-09 10:46:11 +03:00
}
2015-04-09 19:33:02 +03:00
static VALUE
rb_execarg_parent_start1 ( VALUE execarg_obj )
2008-04-28 04:11:46 +04:00
{
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
2012-06-23 05:43:51 +04:00
int unsetenv_others ;
VALUE envopts ;
2012-06-05 16:59:40 +04:00
VALUE ary ;
2012-06-03 12:29:48 +04:00
2015-04-09 15:44:35 +03:00
ary = eargp - > fd_open ;
if ( ary ! = Qfalse ) {
long i ;
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
VALUE elt = RARRAY_AREF ( ary , i ) ;
int fd = FIX2INT ( RARRAY_AREF ( elt , 0 ) ) ;
VALUE param = RARRAY_AREF ( elt , 1 ) ;
VALUE vpath = RARRAY_AREF ( param , 0 ) ;
int flags = NUM2INT ( RARRAY_AREF ( param , 1 ) ) ;
2018-01-19 12:12:06 +03:00
mode_t perm = NUM2MODET ( RARRAY_AREF ( param , 2 ) ) ;
2015-04-09 15:44:35 +03:00
VALUE fd2v = RARRAY_AREF ( param , 3 ) ;
int fd2 ;
if ( NIL_P ( fd2v ) ) {
2015-04-09 19:33:02 +03:00
struct open_struct open_data ;
2015-04-10 12:45:29 +03:00
again :
open_data . fname = vpath ;
open_data . oflags = flags ;
open_data . perm = perm ;
open_data . ret = - 1 ;
open_data . err = EINTR ;
rb_thread_call_without_gvl2 ( open_func , ( void * ) & open_data , RUBY_UBF_IO , 0 ) ;
if ( open_data . ret = = - 1 ) {
if ( open_data . err = = EINTR ) {
rb_thread_check_ints ( ) ;
goto again ;
}
2015-09-07 18:14:46 +03:00
rb_syserr_fail_str ( open_data . err , vpath ) ;
2015-04-10 12:45:29 +03:00
}
fd2 = open_data . ret ;
2015-04-09 15:44:35 +03:00
rb_update_max_fd ( fd2 ) ;
RARRAY_ASET ( param , 3 , INT2FIX ( fd2 ) ) ;
2015-04-09 19:33:02 +03:00
rb_thread_check_ints ( ) ;
2015-04-09 15:44:35 +03:00
}
else {
fd2 = NUM2INT ( fd2v ) ;
}
rb_execarg_addopt ( execarg_obj , INT2FIX ( fd ) , INT2FIX ( fd2 ) ) ;
}
}
2012-06-23 08:23:03 +04:00
eargp - > redirect_fds = check_exec_fds ( eargp ) ;
2012-06-03 12:29:48 +04:00
2012-06-23 15:35:32 +04:00
ary = eargp - > fd_dup2 ;
if ( ary ! = Qfalse ) {
2018-05-09 10:46:11 +03:00
rb_execarg_allocate_dup2_tmpbuf ( eargp , RARRAY_LEN ( ary ) ) ;
2012-06-05 16:59:40 +04:00
}
2012-06-23 05:43:51 +04:00
unsetenv_others = eargp - > unsetenv_others_given & & eargp - > unsetenv_others_do ;
2012-06-23 12:18:34 +04:00
envopts = eargp - > env_modification ;
2015-06-19 20:49:27 +03:00
if ( ALWAYS_NEED_ENVP | | unsetenv_others | | envopts ! = Qfalse ) {
2012-06-03 12:29:48 +04:00
VALUE envtbl , envp_str , envp_buf ;
char * p , * ep ;
2012-06-23 05:43:51 +04:00
if ( unsetenv_others ) {
2012-06-03 12:29:48 +04:00
envtbl = rb_hash_new ( ) ;
}
else {
2021-09-13 21:59:04 +03:00
envtbl = rb_env_to_hash ( ) ;
2012-06-03 12:29:48 +04:00
}
hide_obj ( envtbl ) ;
2012-06-23 14:01:46 +04:00
if ( envopts ! = Qfalse ) {
2013-12-08 04:41:01 +04:00
st_table * stenv = RHASH_TBL_RAW ( envtbl ) ;
2012-06-03 12:29:48 +04:00
long i ;
for ( i = 0 ; i < RARRAY_LEN ( envopts ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE pair = RARRAY_AREF ( envopts , i ) ;
VALUE key = RARRAY_AREF ( pair , 0 ) ;
VALUE val = RARRAY_AREF ( pair , 1 ) ;
2012-06-03 12:29:48 +04:00
if ( NIL_P ( val ) ) {
2013-12-08 04:41:01 +04:00
st_data_t stkey = ( st_data_t ) key ;
st_delete ( stenv , & stkey , NULL ) ;
2012-06-03 12:29:48 +04:00
}
else {
2013-12-08 04:41:01 +04:00
st_insert ( stenv , ( st_data_t ) key , ( st_data_t ) val ) ;
* include/ruby/ruby.h: rename OBJ_WRITE and OBJ_WRITTEN into
RB_OBJ_WRITE and RB_OBJ_WRITTEN.
* array.c, class.c, compile.c, hash.c, internal.h, iseq.c,
proc.c, process.c, re.c, string.c, variable.c, vm.c,
vm_eval.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: catch up this change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44299 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-12-20 12:07:47 +04:00
RB_OBJ_WRITTEN ( envtbl , Qundef , key ) ;
RB_OBJ_WRITTEN ( envtbl , Qundef , val ) ;
2012-06-03 12:29:48 +04:00
}
}
}
envp_buf = rb_str_buf_new ( 0 ) ;
hide_obj ( envp_buf ) ;
2018-10-31 01:11:51 +03:00
rb_hash_stlike_foreach ( envtbl , fill_envp_buf_i , ( st_data_t ) envp_buf ) ;
2012-06-03 12:29:48 +04:00
envp_str = rb_str_buf_new ( sizeof ( char * ) * ( RHASH_SIZE ( envtbl ) + 1 ) ) ;
hide_obj ( envp_str ) ;
p = RSTRING_PTR ( envp_buf ) ;
ep = p + RSTRING_LEN ( envp_buf ) ;
while ( p < ep ) {
rb_str_buf_cat ( envp_str , ( char * ) & p , sizeof ( p ) ) ;
p + = strlen ( p ) + 1 ;
}
p = NULL ;
rb_str_buf_cat ( envp_str , ( char * ) & p , sizeof ( p ) ) ;
2018-05-14 06:30:03 +03:00
eargp - > envp_str =
rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString ( envp_str ) ;
2012-06-23 03:09:16 +04:00
eargp - > envp_buf = envp_buf ;
2012-06-03 12:29:48 +04:00
/*
char * * tmp_envp = ( char * * ) RSTRING_PTR ( envp_str ) ;
while ( * tmp_envp ) {
printf ( " %s \n " , * tmp_envp ) ;
tmp_envp + + ;
}
*/
}
2015-04-09 15:44:35 +03:00
RB_GC_GUARD ( execarg_obj ) ;
2015-04-09 19:33:02 +03:00
return Qnil ;
}
2015-04-09 15:44:35 +03:00
2015-04-09 19:33:02 +03:00
void
rb_execarg_parent_start ( VALUE execarg_obj )
{
int state ;
rb_protect ( rb_execarg_parent_start1 , execarg_obj , & state ) ;
if ( state ) {
rb_execarg_parent_end ( execarg_obj ) ;
rb_jump_tag ( state ) ;
}
2015-04-09 15:44:35 +03:00
}
2015-05-22 13:42:09 +03:00
static VALUE
execarg_parent_end ( VALUE execarg_obj )
2015-04-09 15:44:35 +03:00
{
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
int err = errno ;
VALUE ary ;
ary = eargp - > fd_open ;
if ( ary ! = Qfalse ) {
long i ;
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
VALUE elt = RARRAY_AREF ( ary , i ) ;
VALUE param = RARRAY_AREF ( elt , 1 ) ;
VALUE fd2v ;
int fd2 ;
fd2v = RARRAY_AREF ( param , 3 ) ;
if ( ! NIL_P ( fd2v ) ) {
fd2 = FIX2INT ( fd2v ) ;
2015-04-09 19:33:02 +03:00
parent_redirect_close ( fd2 ) ;
2015-04-09 15:44:35 +03:00
RARRAY_ASET ( param , 3 , Qnil ) ;
}
}
}
errno = err ;
2015-05-22 13:42:09 +03:00
return execarg_obj ;
}
void
rb_execarg_parent_end ( VALUE execarg_obj )
{
execarg_parent_end ( execarg_obj ) ;
2012-06-21 01:25:20 +04:00
RB_GC_GUARD ( execarg_obj ) ;
2008-04-28 04:11:46 +04:00
}
2015-09-07 17:45:31 +03:00
static void
rb_exec_fail ( struct rb_execarg * eargp , int err , const char * errmsg )
{
if ( ! errmsg | | ! * errmsg ) return ;
if ( strcmp ( errmsg , " chdir " ) = = 0 ) {
rb_sys_fail_str ( eargp - > chdir_dir ) ;
}
rb_sys_fail ( errmsg ) ;
}
#if 0
void
rb_execarg_fail ( VALUE execarg_obj , int err , const char * errmsg )
{
if ( ! errmsg | | ! * errmsg ) return ;
rb_exec_fail ( rb_execarg_get ( execarg_obj ) , err , errmsg ) ;
RB_GC_GUARD ( execarg_obj ) ;
}
# endif
2019-08-29 04:23:14 +03:00
VALUE
rb_f_exec ( int argc , const VALUE * argv )
{
VALUE execarg_obj , fail_str ;
struct rb_execarg * eargp ;
# define CHILD_ERRMSG_BUFLEN 80
char errmsg [ CHILD_ERRMSG_BUFLEN ] = { ' \0 ' } ;
2020-02-11 09:52:25 +03:00
int err , state ;
2019-08-29 04:23:14 +03:00
execarg_obj = rb_execarg_new ( argc , argv , TRUE , FALSE ) ;
eargp = rb_execarg_get ( execarg_obj ) ;
if ( mjit_enabled ) mjit_finish ( false ) ; // avoid leaking resources, and do not leave files. XXX: JIT-ed handle can leak after exec error is rescued.
before_exec ( ) ; /* stop timer thread before redirects */
2020-02-11 09:52:25 +03:00
rb_protect ( rb_execarg_parent_start1 , execarg_obj , & state ) ;
if ( state ) {
execarg_parent_end ( execarg_obj ) ;
after_exec ( ) ; /* restart timer thread */
rb_jump_tag ( state ) ;
}
2019-08-29 04:23:14 +03:00
fail_str = eargp - > use_shell ? eargp - > invoke . sh . shell_script : eargp - > invoke . cmd . command_name ;
err = exec_async_signal_safe ( eargp , errmsg , sizeof ( errmsg ) ) ;
after_exec ( ) ; /* restart timer thread */
rb_exec_fail ( eargp , err , errmsg ) ;
RB_GC_GUARD ( execarg_obj ) ;
rb_syserr_fail_str ( err , fail_str ) ;
UNREACHABLE_RETURN ( Qnil ) ;
}
2020-05-10 18:24:14 +03:00
NORETURN ( static VALUE f_exec ( int c , const VALUE * a , VALUE _ ) ) ;
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2008-12-05 18:09:59 +03:00
* exec ( [ env , ] command . . . [ , options ] )
2004-06-29 05:17:39 +04:00
*
2013-05-31 12:58:06 +04:00
* Replaces the current process by running the given external _command_ , which
* can take one of the following forms :
*
* [ < code > exec ( commandline ) < / code > ]
* command line string which is passed to the standard shell
* [ < code > exec ( cmdname , arg1 , . . . ) < / code > ]
* command name and one or more arguments ( no shell )
* [ < code > exec ( [ cmdname , argv0 ] , arg1 , . . . ) < / code > ]
* command name , argv [ 0 ] and zero or more arguments ( no shell )
*
* In the first form , the string is taken as a command line that is subject to
* shell expansion before being executed .
*
* The standard shell always means < code > " /bin/sh " < / code > on Unix - like systems ,
2021-07-30 13:20:09 +03:00
* otherwise , < code > ENV [ " RUBYSHELL " ] < / code > or < code > ENV [ " COMSPEC " ] < / code > on
2021-08-03 12:16:32 +03:00
* Windows and similar . The command is passed as an argument to the
* < code > " -c " < / code > switch to the shell , except in the case of + COMSPEC + .
2013-05-31 12:58:06 +04:00
*
* If the string from the first form ( < code > exec ( " command " ) < / code > ) follows
* these simple rules :
*
* * no meta characters
2021-07-31 05:38:27 +03:00
* * not starting with shell reserved word or special built - in
2013-05-31 12:58:06 +04:00
* * Ruby invokes the command directly without shell
*
* You can force shell invocation by adding " ; " to the string ( because " ; " is
* a meta character ) .
*
2013-04-03 15:55:18 +04:00
* Note that this behavior is observable by pid obtained
2013-05-31 12:58:06 +04:00
* ( return value of spawn ( ) and IO # pid for IO . popen ) is the pid of the invoked
* command , not shell .
2009-11-10 02:23:23 +03:00
*
2013-05-31 12:58:06 +04:00
* In the second form ( < code > exec ( " command1 " , " arg1 " , . . . ) < / code > ) , the first
* is taken as a command name and the rest are passed as parameters to command
* with no shell expansion .
2008-12-05 18:09:59 +03:00
*
2013-05-31 12:58:06 +04:00
* In the third form ( < code > exec ( [ " command " , " argv0 " ] , " arg1 " , . . . ) < / code > ) ,
* starting a two - element array at the beginning of the command , the first
* element is the command to be executed , and the second argument is used as
* the < code > argv [ 0 ] < / code > value , which may show up in process listings .
2008-12-05 18:09:59 +03:00
*
2013-05-31 12:58:06 +04:00
* In order to execute the command , one of the < code > exec ( 2 ) < / code > system
* calls are used , so the running command may inherit some of the environment
2008-10-04 17:33:22 +04:00
* of the original program ( including open file descriptors ) .
2008-04-24 18:46:39 +04:00
*
2013-05-31 12:58:06 +04:00
* This behavior is modified by the given + env + and + options + parameters . See
* : : spawn for details .
*
2019-03-28 06:33:35 +03:00
* If the command fails to execute ( typically Errno : : ENOENT when
2013-05-31 12:58:06 +04:00
* it was not found ) a SystemCallError exception is raised .
*
* This method modifies process attributes according to given + options + before
* < code > exec ( 2 ) < / code > system call . See : : spawn for more details about the
* given + options + .
2012-06-14 00:55:40 +04:00
*
2013-05-31 12:58:06 +04:00
* The modified attributes may be retained when < code > exec ( 2 ) < / code > system
* call fails .
*
* For example , hard resource limits are not restorable .
*
* Consider to create a child process using : : spawn or Kernel # system if this
* is not acceptable .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* exec " echo * " # echoes list of files in current directory
* # never get here
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* exec " echo " , " * " # echoes an asterisk
* # never get here
*/
2019-08-28 12:19:11 +03:00
static VALUE
f_exec ( int c , const VALUE * a , VALUE _ )
{
2020-05-10 18:24:14 +03:00
rb_f_exec ( c , a ) ;
UNREACHABLE_RETURN ( Qnil ) ;
2019-08-28 12:19:11 +03:00
}
2008-12-23 16:15:54 +03:00
# define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
2015-09-07 17:45:31 +03:00
# define ERRMSG1(str, a) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a)); } while (0)
# define ERRMSG2(str, a, b) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a), (b)); } while (0)
2008-12-23 16:15:54 +03:00
2015-09-12 08:30:05 +03:00
static int fd_get_cloexec ( int fd , char * errmsg , size_t errmsg_buflen ) ;
static int fd_set_cloexec ( int fd , char * errmsg , size_t errmsg_buflen ) ;
static int fd_clear_cloexec ( int fd , char * errmsg , size_t errmsg_buflen ) ;
2008-05-12 18:15:32 +04:00
static int
2012-06-23 04:18:32 +04:00
save_redirect_fd ( int fd , struct rb_execarg * sargp , char * errmsg , size_t errmsg_buflen )
2008-05-12 18:15:32 +04:00
{
2012-06-23 04:18:32 +04:00
if ( sargp ) {
2015-09-12 08:30:05 +03:00
VALUE newary , redirection ;
int save_fd = redirect_cloexec_dup ( fd ) , cloexec ;
2008-12-23 16:15:54 +03:00
if ( save_fd = = - 1 ) {
2009-12-31 08:22:11 +03:00
if ( errno = = EBADF )
return 0 ;
2008-12-23 16:15:54 +03:00
ERRMSG ( " dup " ) ;
return - 1 ;
}
2011-07-20 17:26:10 +04:00
rb_update_max_fd ( save_fd ) ;
2012-06-23 15:35:32 +04:00
newary = sargp - > fd_dup2 ;
if ( newary = = Qfalse ) {
2008-05-12 18:15:32 +04:00
newary = hide_obj ( rb_ary_new ( ) ) ;
2012-06-23 15:35:32 +04:00
sargp - > fd_dup2 = newary ;
2008-05-12 18:15:32 +04:00
}
2015-09-12 08:30:05 +03:00
cloexec = fd_get_cloexec ( fd , errmsg , errmsg_buflen ) ;
redirection = hide_obj ( rb_assoc_new ( INT2FIX ( fd ) , INT2FIX ( save_fd ) ) ) ;
if ( cloexec ) rb_ary_push ( redirection , Qtrue ) ;
rb_ary_push ( newary , redirection ) ;
2008-05-12 18:15:32 +04:00
2012-06-23 15:35:32 +04:00
newary = sargp - > fd_close ;
if ( newary = = Qfalse ) {
2008-05-12 18:15:32 +04:00
newary = hide_obj ( rb_ary_new ( ) ) ;
2012-06-23 15:35:32 +04:00
sargp - > fd_close = newary ;
2008-05-12 18:15:32 +04:00
}
rb_ary_push ( newary , hide_obj ( rb_assoc_new ( INT2FIX ( save_fd ) , Qnil ) ) ) ;
}
return 0 ;
}
2008-04-24 18:46:39 +04:00
static int
intcmp ( const void * a , const void * b )
{
return * ( int * ) a - * ( int * ) b ;
}
2008-12-04 18:35:08 +03:00
static int
intrcmp ( const void * a , const void * b )
{
return * ( int * ) b - * ( int * ) a ;
}
2012-06-05 16:59:40 +04:00
struct run_exec_dup2_fd_pair {
int oldfd ;
int newfd ;
long older_index ;
long num_newer ;
2015-09-12 08:30:05 +03:00
int cloexec ;
2012-06-05 16:59:40 +04:00
} ;
static long
run_exec_dup2_tmpbuf_size ( long n )
{
return sizeof ( struct run_exec_dup2_fd_pair ) * n ;
}
2015-09-12 08:30:05 +03:00
/* This function should be async-signal-safe. Actually it is. */
static int
fd_get_cloexec ( int fd , char * errmsg , size_t errmsg_buflen )
{
# ifdef F_GETFD
int ret = 0 ;
ret = fcntl ( fd , F_GETFD ) ; /* async-signal-safe */
if ( ret = = - 1 ) {
ERRMSG ( " fcntl(F_GETFD) " ) ;
return - 1 ;
}
if ( ret & FD_CLOEXEC ) return 1 ;
# endif
return 0 ;
}
/* This function should be async-signal-safe. Actually it is. */
static int
fd_set_cloexec ( int fd , char * errmsg , size_t errmsg_buflen )
{
# ifdef F_GETFD
int ret = 0 ;
ret = fcntl ( fd , F_GETFD ) ; /* async-signal-safe */
if ( ret = = - 1 ) {
ERRMSG ( " fcntl(F_GETFD) " ) ;
return - 1 ;
}
if ( ! ( ret & FD_CLOEXEC ) ) {
ret | = FD_CLOEXEC ;
ret = fcntl ( fd , F_SETFD , ret ) ; /* async-signal-safe */
if ( ret = = - 1 ) {
ERRMSG ( " fcntl(F_SETFD) " ) ;
return - 1 ;
}
}
# endif
return 0 ;
}
2015-04-09 14:35:52 +03:00
/* This function should be async-signal-safe. Actually it is. */
static int
fd_clear_cloexec ( int fd , char * errmsg , size_t errmsg_buflen )
{
# ifdef F_GETFD
int ret ;
ret = fcntl ( fd , F_GETFD ) ; /* async-signal-safe */
if ( ret = = - 1 ) {
ERRMSG ( " fcntl(F_GETFD) " ) ;
return - 1 ;
}
if ( ret & FD_CLOEXEC ) {
ret & = ~ FD_CLOEXEC ;
ret = fcntl ( fd , F_SETFD , ret ) ; /* async-signal-safe */
if ( ret = = - 1 ) {
ERRMSG ( " fcntl(F_SETFD) " ) ;
return - 1 ;
}
}
# endif
return 0 ;
}
2012-06-24 17:35:56 +04:00
/* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
2008-04-24 18:46:39 +04:00
static int
2012-06-23 04:18:32 +04:00
run_exec_dup2 ( VALUE ary , VALUE tmpbuf , struct rb_execarg * sargp , char * errmsg , size_t errmsg_buflen )
2008-04-24 18:46:39 +04:00
{
2009-04-25 13:26:22 +04:00
long n , i ;
2008-04-24 18:46:39 +04:00
int ret ;
int extra_fd = - 1 ;
2018-05-09 10:46:11 +03:00
struct rb_imemo_tmpbuf_struct * buf = ( void * ) tmpbuf ;
struct run_exec_dup2_fd_pair * pairs = ( void * ) buf - > ptr ;
2008-04-24 18:46:39 +04:00
n = RARRAY_LEN ( ary ) ;
/* initialize oldfd and newfd: O(n) */
for ( i = 0 ; i < n ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE elt = RARRAY_AREF ( ary , i ) ;
pairs [ i ] . oldfd = FIX2INT ( RARRAY_AREF ( elt , 1 ) ) ;
pairs [ i ] . newfd = FIX2INT ( RARRAY_AREF ( elt , 0 ) ) ; /* unique */
2015-09-12 08:30:05 +03:00
pairs [ i ] . cloexec = RARRAY_LEN ( elt ) > 2 & & RTEST ( RARRAY_AREF ( elt , 2 ) ) ;
2008-04-24 18:46:39 +04:00
pairs [ i ] . older_index = - 1 ;
}
/* sort the table by oldfd: O(n log n) */
2012-06-23 04:18:32 +04:00
if ( ! sargp )
2012-06-05 16:59:40 +04:00
qsort ( pairs , n , sizeof ( struct run_exec_dup2_fd_pair ) , intcmp ) ; /* hopefully async-signal-safe */
2008-12-04 18:35:08 +03:00
else
2012-06-05 16:59:40 +04:00
qsort ( pairs , n , sizeof ( struct run_exec_dup2_fd_pair ) , intrcmp ) ;
2008-04-24 18:46:39 +04:00
/* initialize older_index and num_newer: O(n log n) */
for ( i = 0 ; i < n ; i + + ) {
int newfd = pairs [ i ] . newfd ;
2012-06-05 16:59:40 +04:00
struct run_exec_dup2_fd_pair key , * found ;
2008-04-24 18:46:39 +04:00
key . oldfd = newfd ;
2012-06-05 16:59:40 +04:00
found = bsearch ( & key , pairs , n , sizeof ( struct run_exec_dup2_fd_pair ) , intcmp ) ; /* hopefully async-signal-safe */
2008-04-24 18:46:39 +04:00
pairs [ i ] . num_newer = 0 ;
if ( found ) {
while ( pairs < found & & ( found - 1 ) - > oldfd = = newfd )
found - - ;
while ( found < pairs + n & & found - > oldfd = = newfd ) {
pairs [ i ] . num_newer + + ;
found - > older_index = i ;
found + + ;
}
}
}
/* non-cyclic redirection: O(n) */
for ( i = 0 ; i < n ; i + + ) {
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
long j = i ;
2008-04-24 18:46:39 +04:00
while ( j ! = - 1 & & pairs [ j ] . oldfd ! = - 1 & & pairs [ j ] . num_newer = = 0 ) {
2012-06-23 04:18:32 +04:00
if ( save_redirect_fd ( pairs [ j ] . newfd , sargp , errmsg , errmsg_buflen ) < 0 ) /* async-signal-safe */
2008-10-09 18:31:32 +04:00
goto fail ;
2012-06-05 14:16:11 +04:00
ret = redirect_dup2 ( pairs [ j ] . oldfd , pairs [ j ] . newfd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) {
ERRMSG ( " dup2 " ) ;
2008-04-24 18:46:39 +04:00
goto fail ;
2008-12-23 16:15:54 +03:00
}
2015-09-12 08:30:05 +03:00
if ( pairs [ j ] . cloexec & &
fd_set_cloexec ( pairs [ j ] . newfd , errmsg , errmsg_buflen ) ) {
goto fail ;
}
2012-06-05 14:16:11 +04:00
rb_update_max_fd ( pairs [ j ] . newfd ) ; /* async-signal-safe but don't need to call it in a child process. */
2008-04-24 18:46:39 +04:00
pairs [ j ] . oldfd = - 1 ;
j = pairs [ j ] . older_index ;
if ( j ! = - 1 )
pairs [ j ] . num_newer - - ;
}
}
/* cyclic redirection: O(n) */
for ( i = 0 ; i < n ; i + + ) {
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
long j ;
2008-04-24 18:46:39 +04:00
if ( pairs [ i ] . oldfd = = - 1 )
continue ;
if ( pairs [ i ] . oldfd = = pairs [ i ] . newfd ) { /* self cycle */
2015-04-09 14:35:52 +03:00
if ( fd_clear_cloexec ( pairs [ i ] . oldfd , errmsg , errmsg_buflen ) = = - 1 ) /* async-signal-safe */
2008-04-24 18:46:39 +04:00
goto fail ;
pairs [ i ] . oldfd = - 1 ;
continue ;
}
if ( extra_fd = = - 1 ) {
2012-06-05 14:16:11 +04:00
extra_fd = redirect_dup ( pairs [ i ] . oldfd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( extra_fd = = - 1 ) {
ERRMSG ( " dup " ) ;
2008-04-24 18:46:39 +04:00
goto fail ;
2008-12-23 16:15:54 +03:00
}
2011-07-20 17:26:10 +04:00
rb_update_max_fd ( extra_fd ) ;
2008-04-24 18:46:39 +04:00
}
else {
2012-06-05 14:16:11 +04:00
ret = redirect_dup2 ( pairs [ i ] . oldfd , extra_fd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) {
ERRMSG ( " dup2 " ) ;
2008-04-24 18:46:39 +04:00
goto fail ;
2008-12-23 16:15:54 +03:00
}
2011-07-20 17:26:10 +04:00
rb_update_max_fd ( extra_fd ) ;
2008-04-24 18:46:39 +04:00
}
pairs [ i ] . oldfd = extra_fd ;
j = pairs [ i ] . older_index ;
pairs [ i ] . older_index = - 1 ;
while ( j ! = - 1 ) {
2012-06-05 14:16:11 +04:00
ret = redirect_dup2 ( pairs [ j ] . oldfd , pairs [ j ] . newfd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) {
ERRMSG ( " dup2 " ) ;
2008-04-24 18:46:39 +04:00
goto fail ;
2008-12-23 16:15:54 +03:00
}
2011-07-20 17:26:10 +04:00
rb_update_max_fd ( ret ) ;
2008-04-24 18:46:39 +04:00
pairs [ j ] . oldfd = - 1 ;
j = pairs [ j ] . older_index ;
}
}
if ( extra_fd ! = - 1 ) {
2012-06-05 14:16:11 +04:00
ret = redirect_close ( extra_fd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) {
ERRMSG ( " close " ) ;
2008-04-24 18:46:39 +04:00
goto fail ;
2008-12-23 16:15:54 +03:00
}
2008-04-24 18:46:39 +04:00
}
return 0 ;
2008-08-04 09:08:57 +04:00
fail :
2008-04-24 18:46:39 +04:00
return - 1 ;
}
2012-06-06 15:58:09 +04:00
/* This function should be async-signal-safe. Actually it is. */
2008-04-24 18:46:39 +04:00
static int
2008-12-23 16:15:54 +03:00
run_exec_close ( VALUE ary , char * errmsg , size_t errmsg_buflen )
2008-04-24 18:46:39 +04:00
{
2011-03-08 03:08:16 +03:00
long i ;
int ret ;
2008-04-24 18:46:39 +04:00
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE elt = RARRAY_AREF ( ary , i ) ;
int fd = FIX2INT ( RARRAY_AREF ( elt , 0 ) ) ;
2012-06-05 14:16:11 +04:00
ret = redirect_close ( fd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) {
ERRMSG ( " close " ) ;
2008-04-24 18:46:39 +04:00
return - 1 ;
2008-12-23 16:15:54 +03:00
}
2008-04-24 18:46:39 +04:00
}
return 0 ;
}
2012-06-24 17:35:56 +04:00
/* This function should be async-signal-safe when sargp is NULL. Actually it is. */
2008-12-03 18:02:10 +03:00
static int
2012-06-23 04:18:32 +04:00
run_exec_dup2_child ( VALUE ary , struct rb_execarg * sargp , char * errmsg , size_t errmsg_buflen )
2008-12-03 18:02:10 +03:00
{
2011-03-08 03:08:16 +03:00
long i ;
int ret ;
2008-12-03 18:02:10 +03:00
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE elt = RARRAY_AREF ( ary , i ) ;
int newfd = FIX2INT ( RARRAY_AREF ( elt , 0 ) ) ;
int oldfd = FIX2INT ( RARRAY_AREF ( elt , 1 ) ) ;
2008-12-03 18:02:10 +03:00
2012-06-23 04:18:32 +04:00
if ( save_redirect_fd ( newfd , sargp , errmsg , errmsg_buflen ) < 0 ) /* async-signal-safe */
2008-12-03 18:02:10 +03:00
return - 1 ;
2012-06-05 14:16:11 +04:00
ret = redirect_dup2 ( oldfd , newfd ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) {
ERRMSG ( " dup2 " ) ;
return - 1 ;
}
2011-07-20 17:26:10 +04:00
rb_update_max_fd ( newfd ) ;
2008-12-03 18:02:10 +03:00
}
return 0 ;
}
2008-04-24 18:46:39 +04:00
# ifdef HAVE_SETPGID
2012-06-24 17:35:56 +04:00
/* This function should be async-signal-safe when sargp is NULL. Actually it is. */
2008-04-24 18:46:39 +04:00
static int
2012-06-23 04:18:32 +04:00
run_exec_pgroup ( const struct rb_execarg * eargp , struct rb_execarg * sargp , char * errmsg , size_t errmsg_buflen )
2008-04-24 18:46:39 +04:00
{
/*
2014-09-02 17:56:35 +04:00
* If FD_CLOEXEC is available , rb_fork_async_signal_safe waits the child ' s execve .
* So setpgid is done in the child when rb_fork_async_signal_safe is returned in
* include/ruby/intern.h,
include/ruby/io.h,
include/ruby/ruby.h,
include/ruby/win32.h,
include/ruby/backward/rubysig.h,
bignum.c,
gc.c,
io.c,
process.c,
safe.c,
struct.c,
thread.c,
ext/socket/rubysocket.h,
ext/-test-/old_thread_select: Remove deprecated definitions
[ruby-core:60581] [Feature #9502]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44955 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2014-02-14 19:16:31 +04:00
* the parent .
2008-04-24 18:46:39 +04:00
* No race condition , even without setpgid from the parent .
2012-06-22 15:30:29 +04:00
* ( Is there an environment which has setpgid but no FD_CLOEXEC ? )
2008-05-12 18:15:32 +04:00
*/
2008-12-23 16:15:54 +03:00
int ret ;
2013-03-21 20:11:32 +04:00
rb_pid_t pgroup ;
2012-06-22 15:30:29 +04:00
2012-06-23 03:09:16 +04:00
pgroup = eargp - > pgroup_pgid ;
2012-06-22 15:30:29 +04:00
if ( pgroup = = - 1 )
return 0 ;
2012-06-23 04:18:32 +04:00
if ( sargp ) {
2008-05-12 18:15:32 +04:00
/* maybe meaningless with no fork environment... */
2012-06-23 04:18:32 +04:00
sargp - > pgroup_given = 1 ;
sargp - > pgroup_pgid = getpgrp ( ) ;
2008-05-12 18:15:32 +04:00
}
2012-06-22 15:30:29 +04:00
2008-04-24 18:46:39 +04:00
if ( pgroup = = 0 ) {
2012-06-05 14:16:11 +04:00
pgroup = getpid ( ) ; /* async-signal-safe */
2008-04-24 18:46:39 +04:00
}
2012-06-05 14:16:11 +04:00
ret = setpgid ( getpid ( ) , pgroup ) ; /* async-signal-safe */
2008-12-23 16:15:54 +03:00
if ( ret = = - 1 ) ERRMSG ( " setpgid " ) ;
return ret ;
2008-04-24 18:46:39 +04:00
}
# endif
2011-03-07 11:44:45 +03:00
# if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2012-06-24 17:35:56 +04:00
/* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
2008-04-24 18:46:39 +04:00
static int
2012-06-23 04:18:32 +04:00
run_exec_rlimit ( VALUE ary , struct rb_execarg * sargp , char * errmsg , size_t errmsg_buflen )
2008-04-24 18:46:39 +04:00
{
2011-03-08 03:08:16 +03:00
long i ;
2008-04-24 18:46:39 +04:00
for ( i = 0 ; i < RARRAY_LEN ( ary ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE elt = RARRAY_AREF ( ary , i ) ;
int rtype = NUM2INT ( RARRAY_AREF ( elt , 0 ) ) ;
2008-04-24 18:46:39 +04:00
struct rlimit rlim ;
2012-06-23 04:18:32 +04:00
if ( sargp ) {
2008-07-01 12:31:55 +04:00
VALUE tmp , newary ;
2008-12-23 16:15:54 +03:00
if ( getrlimit ( rtype , & rlim ) = = - 1 ) {
ERRMSG ( " getrlimit " ) ;
2008-05-12 18:15:32 +04:00
return - 1 ;
2008-12-23 16:15:54 +03:00
}
2013-05-13 13:56:22 +04:00
tmp = hide_obj ( rb_ary_new3 ( 3 , RARRAY_AREF ( elt , 0 ) ,
2008-07-01 12:31:55 +04:00
RLIM2NUM ( rlim . rlim_cur ) ,
RLIM2NUM ( rlim . rlim_max ) ) ) ;
2012-06-23 11:30:26 +04:00
if ( sargp - > rlimit_limits = = Qfalse )
newary = sargp - > rlimit_limits = hide_obj ( rb_ary_new ( ) ) ;
2012-08-23 11:45:46 +04:00
else
2012-06-23 11:30:26 +04:00
newary = sargp - > rlimit_limits ;
2008-05-12 18:15:32 +04:00
rb_ary_push ( newary , tmp ) ;
}
2013-05-13 13:56:22 +04:00
rlim . rlim_cur = NUM2RLIM ( RARRAY_AREF ( elt , 1 ) ) ;
rlim . rlim_max = NUM2RLIM ( RARRAY_AREF ( elt , 2 ) ) ;
2012-06-05 14:16:11 +04:00
if ( setrlimit ( rtype , & rlim ) = = - 1 ) { /* hopefully async-signal-safe */
2008-12-23 16:15:54 +03:00
ERRMSG ( " setrlimit " ) ;
2008-04-24 18:46:39 +04:00
return - 1 ;
2008-12-23 16:15:54 +03:00
}
2008-04-24 18:46:39 +04:00
}
return 0 ;
}
# endif
2014-09-03 02:51:03 +04:00
# if !defined(HAVE_WORKING_FORK)
2012-06-04 06:36:11 +04:00
static VALUE
2013-11-29 11:59:14 +04:00
save_env_i ( RB_BLOCK_CALL_FUNC_ARGLIST ( i , ary ) )
2012-06-04 06:36:11 +04:00
{
rb_ary_push ( ary , hide_obj ( rb_ary_dup ( argv [ 0 ] ) ) ) ;
return Qnil ;
}
static void
2012-06-23 04:18:32 +04:00
save_env ( struct rb_execarg * sargp )
2012-06-04 06:36:11 +04:00
{
2012-06-23 04:18:32 +04:00
if ( ! sargp )
2012-06-22 13:24:21 +04:00
return ;
2012-06-23 12:18:34 +04:00
if ( sargp - > env_modification = = Qfalse ) {
2021-09-13 21:59:04 +03:00
VALUE env = rb_envtbl ( ) ;
2012-06-04 06:36:11 +04:00
if ( RTEST ( env ) ) {
VALUE ary = hide_obj ( rb_ary_new ( ) ) ;
2012-12-02 13:57:47 +04:00
rb_block_call ( env , idEach , 0 , 0 , save_env_i ,
2012-06-04 06:36:11 +04:00
( VALUE ) ary ) ;
2012-06-23 12:18:34 +04:00
sargp - > env_modification = ary ;
2012-06-04 06:36:11 +04:00
}
2012-06-23 12:22:53 +04:00
sargp - > unsetenv_others_given = 1 ;
sargp - > unsetenv_others_do = 1 ;
2012-06-04 06:36:11 +04:00
}
}
# endif
2015-12-27 14:54:59 +03:00
# ifdef _WIN32
# undef chdir
# define chdir(p) rb_w32_uchdir(p)
# endif
2012-06-24 17:35:56 +04:00
/* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
2008-05-12 18:15:32 +04:00
int
2012-06-23 04:18:32 +04:00
rb_execarg_run_options ( const struct rb_execarg * eargp , struct rb_execarg * sargp , char * errmsg , size_t errmsg_buflen )
2008-04-24 18:46:39 +04:00
{
VALUE obj ;
2012-06-23 04:18:32 +04:00
if ( sargp ) {
/* assume that sargp is always NULL on fork-able environments */
2012-06-23 11:30:26 +04:00
MEMZERO ( sargp , struct rb_execarg , 1 ) ;
2012-06-23 04:18:32 +04:00
sargp - > redirect_fds = Qnil ;
2008-05-12 18:15:32 +04:00
}
2008-04-24 18:46:39 +04:00
# ifdef HAVE_SETPGID
2012-06-23 03:09:16 +04:00
if ( eargp - > pgroup_given ) {
2012-06-23 04:18:32 +04:00
if ( run_exec_pgroup ( eargp , sargp , errmsg , errmsg_buflen ) = = - 1 ) /* async-signal-safe */
2008-04-24 18:46:39 +04:00
return - 1 ;
}
# endif
2011-03-07 11:44:45 +03:00
# if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2012-06-23 11:30:26 +04:00
obj = eargp - > rlimit_limits ;
if ( obj ! = Qfalse ) {
2012-06-23 04:18:32 +04:00
if ( run_exec_rlimit ( obj , sargp , errmsg , errmsg_buflen ) = = - 1 ) /* hopefully async-signal-safe */
2008-04-24 18:46:39 +04:00
return - 1 ;
}
# endif
2014-09-03 02:51:03 +04:00
# if !defined(HAVE_WORKING_FORK)
2012-06-23 12:22:53 +04:00
if ( eargp - > unsetenv_others_given & & eargp - > unsetenv_others_do ) {
2012-06-23 04:18:32 +04:00
save_env ( sargp ) ;
2012-06-04 06:36:11 +04:00
rb_env_clear ( ) ;
}
2012-06-23 12:18:34 +04:00
obj = eargp - > env_modification ;
if ( obj ! = Qfalse ) {
2012-06-04 06:36:11 +04:00
long i ;
2012-06-23 04:18:32 +04:00
save_env ( sargp ) ;
2012-06-04 06:36:11 +04:00
for ( i = 0 ; i < RARRAY_LEN ( obj ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE pair = RARRAY_AREF ( obj , i ) ;
VALUE key = RARRAY_AREF ( pair , 0 ) ;
VALUE val = RARRAY_AREF ( pair , 1 ) ;
2012-06-04 06:36:11 +04:00
if ( NIL_P ( val ) )
ruby_setenv ( StringValueCStr ( key ) , 0 ) ;
else
ruby_setenv ( StringValueCStr ( key ) , StringValueCStr ( val ) ) ;
}
}
# endif
2012-06-23 03:09:16 +04:00
if ( eargp - > umask_given ) {
mode_t mask = eargp - > umask_mask ;
2012-06-05 14:16:11 +04:00
mode_t oldmask = umask ( mask ) ; /* never fail */ /* async-signal-safe */
2012-06-23 04:18:32 +04:00
if ( sargp ) {
sargp - > umask_given = 1 ;
sargp - > umask_mask = oldmask ;
2012-06-20 16:27:09 +04:00
}
2008-04-24 18:46:39 +04:00
}
2012-06-23 15:35:32 +04:00
obj = eargp - > fd_dup2 ;
if ( obj ! = Qfalse ) {
2012-06-23 04:18:32 +04:00
if ( run_exec_dup2 ( obj , eargp - > dup2_tmpbuf , sargp , errmsg , errmsg_buflen ) = = - 1 ) /* hopefully async-signal-safe */
2008-04-24 18:46:39 +04:00
return - 1 ;
}
2012-06-23 15:35:32 +04:00
obj = eargp - > fd_close ;
if ( obj ! = Qfalse ) {
2012-06-23 04:18:32 +04:00
if ( sargp )
2008-05-12 18:15:32 +04:00
rb_warn ( " cannot close fd before spawn " ) ;
else {
2012-06-05 14:16:11 +04:00
if ( run_exec_close ( obj , errmsg , errmsg_buflen ) = = - 1 ) /* async-signal-safe */
2008-05-12 18:15:32 +04:00
return - 1 ;
}
2008-04-24 18:46:39 +04:00
}
2014-09-03 02:51:03 +04:00
# ifdef HAVE_WORKING_FORK
2018-08-17 02:56:08 +03:00
if ( eargp - > close_others_do ) {
2012-06-23 08:23:03 +04:00
rb_close_before_exec ( 3 , eargp - > close_others_maxhint , eargp - > redirect_fds ) ; /* async-signal-safe */
2008-04-24 18:46:39 +04:00
}
2008-04-25 05:55:22 +04:00
# endif
2008-04-24 18:46:39 +04:00
2012-06-23 15:35:32 +04:00
obj = eargp - > fd_dup2_child ;
if ( obj ! = Qfalse ) {
2012-06-23 04:18:32 +04:00
if ( run_exec_dup2_child ( obj , sargp , errmsg , errmsg_buflen ) = = - 1 ) /* async-signal-safe */
2008-12-03 18:02:10 +03:00
return - 1 ;
}
2012-06-23 10:23:35 +04:00
if ( eargp - > chdir_given ) {
2012-06-23 04:18:32 +04:00
if ( sargp ) {
2012-06-23 10:23:35 +04:00
sargp - > chdir_given = 1 ;
2020-02-12 05:53:51 +03:00
sargp - > chdir_dir = hide_obj ( rb_dir_getwd_ospath ( ) ) ;
2012-03-03 17:53:53 +04:00
}
2012-06-23 10:23:35 +04:00
if ( chdir ( RSTRING_PTR ( eargp - > chdir_dir ) ) = = - 1 ) { /* async-signal-safe */
2012-03-03 17:53:53 +04:00
ERRMSG ( " chdir " ) ;
return - 1 ;
}
}
2012-10-09 12:13:29 +04:00
# ifdef HAVE_SETGID
if ( eargp - > gid_given ) {
if ( setgid ( eargp - > gid ) < 0 ) {
ERRMSG ( " setgid " ) ;
return - 1 ;
}
}
# endif
# ifdef HAVE_SETUID
if ( eargp - > uid_given ) {
if ( setuid ( eargp - > uid ) < 0 ) {
ERRMSG ( " setuid " ) ;
return - 1 ;
}
}
# endif
2012-06-23 04:18:32 +04:00
if ( sargp ) {
2012-06-23 15:35:32 +04:00
VALUE ary = sargp - > fd_dup2 ;
if ( ary ! = Qfalse ) {
2018-05-09 10:46:11 +03:00
rb_execarg_allocate_dup2_tmpbuf ( sargp , RARRAY_LEN ( ary ) ) ;
2012-06-06 07:39:40 +04:00
}
}
2018-11-22 11:46:51 +03:00
{
int preserve = errno ;
stdfd_clear_nonblock ( ) ;
errno = preserve ;
}
2012-06-06 07:39:40 +04:00
2008-04-24 18:46:39 +04:00
return 0 ;
}
2012-06-09 06:09:10 +04:00
/* This function should be async-signal-safe. Hopefully it is. */
2012-06-10 05:29:58 +04:00
int
2012-06-23 03:09:16 +04:00
rb_exec_async_signal_safe ( const struct rb_execarg * eargp , char * errmsg , size_t errmsg_buflen )
2017-11-14 07:42:38 +03:00
{
errno = exec_async_signal_safe ( eargp , errmsg , errmsg_buflen ) ;
return - 1 ;
}
static int
exec_async_signal_safe ( const struct rb_execarg * eargp , char * errmsg , size_t errmsg_buflen )
2004-02-16 09:45:32 +03:00
{
2014-09-03 02:51:03 +04:00
# if !defined(HAVE_WORKING_FORK)
2012-06-22 07:07:26 +04:00
struct rb_execarg sarg , * const sargp = & sarg ;
2012-06-04 06:36:11 +04:00
# else
2012-06-22 07:07:26 +04:00
struct rb_execarg * const sargp = NULL ;
2012-06-04 06:36:11 +04:00
# endif
2017-11-14 07:42:38 +03:00
int err ;
2001-03-28 12:43:25 +04:00
2012-06-23 03:09:16 +04:00
if ( rb_execarg_run_options ( eargp , sargp , errmsg , errmsg_buflen ) < 0 ) { /* hopefully async-signal-safe */
2017-11-14 07:42:38 +03:00
return errno ;
2008-04-24 18:46:39 +04:00
}
2012-06-23 03:09:16 +04:00
if ( eargp - > use_shell ) {
2017-11-14 07:42:38 +03:00
err = proc_exec_sh ( RSTRING_PTR ( eargp - > invoke . sh . shell_script ) , eargp - > envp_str ) ; /* async-signal-safe */
1998-01-16 15:13:05 +03:00
}
else {
2012-06-06 15:49:30 +04:00
char * abspath = NULL ;
2012-06-23 03:09:16 +04:00
if ( ! NIL_P ( eargp - > invoke . cmd . command_abspath ) )
abspath = RSTRING_PTR ( eargp - > invoke . cmd . command_abspath ) ;
2017-11-14 07:42:38 +03:00
err = proc_exec_cmd ( abspath , eargp - > invoke . cmd . argv_str , eargp - > envp_str ) ; /* async-signal-safe */
1998-01-16 15:13:05 +03:00
}
2014-09-03 02:51:03 +04:00
# if !defined(HAVE_WORKING_FORK)
2017-11-14 07:42:38 +03:00
rb_execarg_run_options ( sargp , NULL , errmsg , errmsg_buflen ) ;
2012-06-04 06:36:11 +04:00
# endif
2012-06-10 01:48:42 +04:00
2017-11-14 07:42:38 +03:00
return err ;
1998-01-16 15:13:05 +03:00
}
2014-09-03 02:51:03 +04:00
# ifdef HAVE_WORKING_FORK
2012-06-10 05:46:45 +04:00
/* This function should be async-signal-safe. Hopefully it is. */
2007-09-20 12:28:03 +04:00
static int
2008-12-23 16:15:54 +03:00
rb_exec_atfork ( void * arg , char * errmsg , size_t errmsg_buflen )
2007-09-20 12:28:03 +04:00
{
2012-06-09 19:25:34 +04:00
return rb_exec_async_signal_safe ( arg , errmsg , errmsg_buflen ) ; /* hopefully async-signal-safe */
2007-09-20 12:28:03 +04:00
}
2004-03-29 15:17:21 +04:00
# if SIZEOF_INT == SIZEOF_LONG
2005-09-14 12:30:16 +04:00
# define proc_syswait (VALUE (*)(VALUE))rb_syswait
2004-03-29 15:17:21 +04:00
# else
static VALUE
2006-08-13 13:44:16 +04:00
proc_syswait ( VALUE pid )
2004-03-29 15:17:21 +04:00
{
rb_syswait ( ( int ) pid ) ;
return Qnil ;
}
# endif
2008-04-24 18:46:39 +04:00
static int
move_fds_to_avoid_crash ( int * fdp , int n , VALUE fds )
{
2011-11-01 09:56:51 +04:00
int min = 0 ;
2008-04-24 18:46:39 +04:00
int i ;
for ( i = 0 ; i < n ; i + + ) {
int ret ;
while ( RTEST ( rb_hash_lookup ( fds , INT2FIX ( fdp [ i ] ) ) ) ) {
if ( min < = fdp [ i ] )
min = fdp [ i ] + 1 ;
while ( RTEST ( rb_hash_lookup ( fds , INT2FIX ( min ) ) ) )
min + + ;
2011-10-30 19:17:27 +04:00
ret = rb_cloexec_fcntl_dupfd ( fdp [ i ] , min ) ;
2008-04-24 18:46:39 +04:00
if ( ret = = - 1 )
return - 1 ;
2011-10-30 19:17:27 +04:00
rb_update_max_fd ( ret ) ;
2008-04-24 18:46:39 +04:00
close ( fdp [ i ] ) ;
fdp [ i ] = ret ;
}
}
return 0 ;
}
static int
pipe_nocrash ( int filedes [ 2 ] , VALUE fds )
{
int ret ;
2008-07-05 18:12:53 +04:00
ret = rb_pipe ( filedes ) ;
2008-04-24 18:46:39 +04:00
if ( ret = = - 1 )
return - 1 ;
if ( RTEST ( fds ) ) {
int save = errno ;
if ( move_fds_to_avoid_crash ( filedes , 2 , fds ) = = - 1 ) {
close ( filedes [ 0 ] ) ;
close ( filedes [ 1 ] ) ;
return - 1 ;
}
errno = save ;
}
return ret ;
}
2010-09-03 01:40:55 +04:00
# ifndef O_BINARY
# define O_BINARY 0
# endif
2018-05-04 18:18:42 +03:00
static VALUE
rb_thread_sleep_that_takes_VALUE_as_sole_argument ( VALUE n )
{
rb_thread_sleep ( NUM2INT ( n ) ) ;
return Qundef ;
}
2014-09-02 15:47:35 +04:00
static int
2020-12-05 15:05:40 +03:00
handle_fork_error ( int err , struct rb_process_status * status , int * ep , volatile int * try_gc_p )
2014-09-02 15:47:35 +04:00
{
2014-09-05 15:49:04 +04:00
int state = 0 ;
2017-11-14 07:42:38 +03:00
switch ( err ) {
2014-09-02 15:47:35 +04:00
case ENOMEM :
if ( ( * try_gc_p ) - - > 0 & & ! rb_during_gc ( ) ) {
rb_gc ( ) ;
return 0 ;
}
break ;
case EAGAIN :
# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK :
# endif
if ( ! status & & ! ep ) {
rb_thread_sleep ( 1 ) ;
return 0 ;
}
else {
2018-05-04 18:20:17 +03:00
rb_protect ( rb_thread_sleep_that_takes_VALUE_as_sole_argument , INT2FIX ( 1 ) , & state ) ;
2020-12-05 15:05:40 +03:00
if ( status ) status - > status = state ;
2014-09-05 15:49:04 +04:00
if ( ! state ) return 0 ;
2014-09-02 15:47:35 +04:00
}
break ;
}
if ( ep ) {
2017-11-14 07:42:38 +03:00
close ( ep [ 0 ] ) ;
close ( ep [ 1 ] ) ;
errno = err ;
2014-09-02 15:47:35 +04:00
}
2014-09-05 15:49:04 +04:00
if ( state & & ! status ) rb_jump_tag ( state ) ;
2014-09-02 15:47:35 +04:00
return - 1 ;
}
# define prefork() ( \
rb_io_flush ( rb_stdout ) , \
rb_io_flush ( rb_stderr ) \
)
2004-03-29 15:17:21 +04:00
/*
* Forks child process , and returns the process ID in the parent
* process .
*
* If + status + is given , protects from any exceptions and sets the
2012-06-08 06:26:39 +04:00
* jump status to it , and returns - 1. If failed to fork new process
* but no exceptions occurred , sets 0 to it . Otherwise , if forked
* successfully , the value of + status + is undetermined .
2004-03-29 15:17:21 +04:00
*
* In the child process , just returns 0 if + chfunc + is + NULL + .
* Otherwise + chfunc + will be called with + charg + , and then the child
* process exits with + EXIT_SUCCESS + when it returned zero .
*
* In the case of the function is called and returns non - zero value ,
2007-12-31 15:55:50 +03:00
* the child process exits with non - + EXIT_SUCCESS + value ( normally
2004-03-29 15:17:21 +04:00
* 127 ) . And , on the platforms where + FD_CLOEXEC + is available ,
* + errno + is propagated to the parent process , and this function
* returns - 1 in the parent process . On the other platforms , just
* returns pid .
*
2008-04-24 18:46:39 +04:00
* If fds is not Qnil , internal pipe for the errno propagation is
* arranged to avoid conflicts of the hash keys in + fds + .
*
2004-03-29 15:17:21 +04:00
* + chfunc + must not raise any exceptions .
*/
2012-06-09 16:51:01 +04:00
2014-01-25 09:50:44 +04:00
static ssize_t
write_retry ( int fd , const void * buf , size_t len )
{
ssize_t w ;
do {
w = write ( fd , buf , len ) ;
} while ( w < 0 & & errno = = EINTR ) ;
return w ;
}
static ssize_t
read_retry ( int fd , void * buf , size_t len )
{
ssize_t r ;
2018-11-22 11:46:51 +03:00
if ( set_blocking ( fd ) ! = 0 ) {
# ifndef _WIN32
rb_async_bug_errno ( " set_blocking failed reading child error " , errno ) ;
# endif
}
2014-01-25 09:50:44 +04:00
do {
r = read ( fd , buf , len ) ;
} while ( r < 0 & & errno = = EINTR ) ;
return r ;
}
2012-06-09 16:51:01 +04:00
static void
2014-09-02 18:27:10 +04:00
send_child_error ( int fd , char * errmsg , size_t errmsg_buflen )
2012-06-09 16:51:01 +04:00
{
int err ;
err = errno ;
2014-01-25 09:50:44 +04:00
if ( write_retry ( fd , & err , sizeof ( err ) ) < 0 ) err = errno ;
2012-06-09 16:51:01 +04:00
if ( errmsg & & 0 < errmsg_buflen ) {
errmsg [ errmsg_buflen - 1 ] = ' \0 ' ;
errmsg_buflen = strlen ( errmsg ) ;
2014-01-25 09:50:44 +04:00
if ( errmsg_buflen > 0 & & write_retry ( fd , errmsg , errmsg_buflen ) < 0 )
2012-06-09 16:51:01 +04:00
err = errno ;
}
}
static int
2014-09-02 18:27:10 +04:00
recv_child_error ( int fd , int * errp , char * errmsg , size_t errmsg_buflen )
2012-06-09 16:51:01 +04:00
{
2014-09-02 18:27:10 +04:00
int err ;
2012-06-09 16:51:01 +04:00
ssize_t size ;
2014-09-02 18:27:10 +04:00
if ( ( size = read_retry ( fd , & err , sizeof ( err ) ) ) < 0 ) {
2012-06-09 16:51:01 +04:00
err = errno ;
}
* errp = err ;
if ( size = = sizeof ( err ) & &
errmsg & & 0 < errmsg_buflen ) {
2014-09-02 18:27:10 +04:00
ssize_t ret = read_retry ( fd , errmsg , errmsg_buflen - 1 ) ;
2012-06-09 16:51:01 +04:00
if ( 0 < = ret ) {
errmsg [ ret ] = ' \0 ' ;
2008-12-23 16:15:54 +03:00
}
2012-06-09 16:51:01 +04:00
}
2014-09-02 18:27:10 +04:00
close ( fd ) ;
2012-06-09 16:51:01 +04:00
return size ! = 0 ;
}
2014-09-07 05:57:44 +04:00
# ifdef HAVE_WORKING_VFORK
2014-09-05 07:43:28 +04:00
# if !defined(HAVE_GETRESUID) && defined(HAVE_GETUIDX)
/* AIX 7.1 */
static int
getresuid ( rb_uid_t * ruid , rb_uid_t * euid , rb_uid_t * suid )
{
rb_uid_t ret ;
* ruid = getuid ( ) ;
* euid = geteuid ( ) ;
ret = getuidx ( ID_SAVED ) ;
if ( ret = = ( rb_uid_t ) - 1 )
return - 1 ;
* suid = ret ;
return 0 ;
}
# define HAVE_GETRESUID
# endif
# if !defined(HAVE_GETRESGID) && defined(HAVE_GETGIDX)
/* AIX 7.1 */
static int
getresgid ( rb_gid_t * rgid , rb_gid_t * egid , rb_gid_t * sgid )
{
rb_gid_t ret ;
* rgid = getgid ( ) ;
* egid = getegid ( ) ;
ret = getgidx ( ID_SAVED ) ;
if ( ret = = ( rb_gid_t ) - 1 )
return - 1 ;
* sgid = ret ;
return 0 ;
}
# define HAVE_GETRESGID
# endif
2014-09-04 18:56:03 +04:00
static int
has_privilege ( void )
{
/*
* has_privilege ( ) is used to choose vfork ( ) or fork ( ) .
*
* If the process has privilege , the parent process or
* the child process can change UID / GID .
* If vfork ( ) is used to create the child process and
* the parent or child process change effective UID / GID ,
* different privileged processes shares memory .
* It is a bad situation .
* So , fork ( ) should be used .
*/
rb_uid_t ruid , euid ;
rb_gid_t rgid , egid ;
# if defined HAVE_ISSETUGID
if ( issetugid ( ) )
return 1 ;
# endif
# ifdef HAVE_GETRESUID
{
int ret ;
rb_uid_t suid ;
ret = getresuid ( & ruid , & euid , & suid ) ;
if ( ret = = - 1 )
rb_sys_fail ( " getresuid(2) " ) ;
2014-09-05 07:58:42 +04:00
if ( euid ! = suid )
2014-09-04 18:56:03 +04:00
return 1 ;
}
# else
2014-09-05 20:10:16 +04:00
ruid = getuid ( ) ;
euid = geteuid ( ) ;
2014-09-04 18:56:03 +04:00
# endif
2014-09-05 07:58:42 +04:00
if ( euid = = 0 | | euid ! = ruid )
2014-09-04 18:56:03 +04:00
return 1 ;
# ifdef HAVE_GETRESGID
{
int ret ;
rb_gid_t sgid ;
ret = getresgid ( & rgid , & egid , & sgid ) ;
if ( ret = = - 1 )
rb_sys_fail ( " getresgid(2) " ) ;
2014-09-05 07:58:42 +04:00
if ( egid ! = sgid )
2014-09-05 15:36:19 +04:00
return 1 ;
2014-09-04 18:56:03 +04:00
}
# else
2014-09-05 20:10:16 +04:00
rgid = getgid ( ) ;
egid = getegid ( ) ;
2014-09-04 18:56:03 +04:00
# endif
2014-09-06 16:08:02 +04:00
if ( egid ! = rgid )
2014-09-04 18:56:03 +04:00
return 1 ;
return 0 ;
}
2014-09-07 05:10:43 +04:00
# endif
2014-09-04 18:56:03 +04:00
2014-09-06 14:27:54 +04:00
struct child_handler_disabler_state
{
sigset_t sigmask ;
} ;
2014-09-05 16:46:09 +04:00
static void
2014-09-06 14:27:54 +04:00
disable_child_handler_before_fork ( struct child_handler_disabler_state * old )
2014-09-05 16:46:09 +04:00
{
2021-08-16 10:02:49 +03:00
# ifdef HAVE_PTHREAD_SIGMASK
2014-09-05 16:46:09 +04:00
int ret ;
sigset_t all ;
ret = sigfillset ( & all ) ;
if ( ret = = - 1 )
rb_sys_fail ( " sigfillset " ) ;
2014-09-06 14:27:54 +04:00
ret = pthread_sigmask ( SIG_SETMASK , & all , & old - > sigmask ) ; /* not async-signal-safe */
2014-09-05 16:46:09 +04:00
if ( ret ! = 0 ) {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( ret , " pthread_sigmask " ) ;
2014-09-05 16:46:09 +04:00
}
2014-10-11 17:33:14 +04:00
# else
# pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
# endif
2014-09-05 16:46:09 +04:00
}
static void
2014-09-06 14:27:54 +04:00
disable_child_handler_fork_parent ( struct child_handler_disabler_state * old )
2014-09-05 16:46:09 +04:00
{
2021-08-16 10:02:49 +03:00
# ifdef HAVE_PTHREAD_SIGMASK
2014-09-05 16:46:09 +04:00
int ret ;
2014-09-06 14:27:54 +04:00
ret = pthread_sigmask ( SIG_SETMASK , & old - > sigmask , NULL ) ; /* not async-signal-safe */
2014-09-05 16:46:09 +04:00
if ( ret ! = 0 ) {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( ret , " pthread_sigmask " ) ;
2014-09-05 16:46:09 +04:00
}
2014-10-11 17:33:14 +04:00
# else
# pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
# endif
2014-09-05 16:46:09 +04:00
}
/* This function should be async-signal-safe. Actually it is. */
static int
2014-09-06 14:27:54 +04:00
disable_child_handler_fork_child ( struct child_handler_disabler_state * old , char * errmsg , size_t errmsg_buflen )
2014-09-05 16:46:09 +04:00
{
int sig ;
int ret ;
for ( sig = 1 ; sig < NSIG ; sig + + ) {
2017-09-20 02:09:10 +03:00
sig_t handler = signal ( sig , SIG_DFL ) ;
2016-07-03 00:13:26 +03:00
2017-09-20 02:09:10 +03:00
if ( handler = = SIG_ERR & & errno = = EINVAL ) {
continue ; /* Ignore invalid signal number */
}
if ( handler = = SIG_ERR ) {
ERRMSG ( " signal to obtain old action " ) ;
return - 1 ;
}
2016-07-03 00:13:26 +03:00
# ifdef SIGPIPE
2017-09-20 02:09:10 +03:00
if ( sig = = SIGPIPE ) {
continue ;
}
2014-10-11 17:33:14 +04:00
# endif
2017-09-20 02:09:10 +03:00
/* it will be reset to SIG_DFL at execve time, instead */
if ( handler = = SIG_IGN ) {
signal ( sig , SIG_IGN ) ;
}
2014-09-05 16:46:09 +04:00
}
2018-07-05 06:02:33 +03:00
/* non-Ruby child process, ensure cmake can see SIGCHLD */
sigemptyset ( & old - > sigmask ) ;
2014-09-06 14:27:54 +04:00
ret = sigprocmask ( SIG_SETMASK , & old - > sigmask , NULL ) ; /* async-signal-safe */
2014-09-05 16:46:09 +04:00
if ( ret ! = 0 ) {
ERRMSG ( " sigprocmask " ) ;
return - 1 ;
}
return 0 ;
}
2014-09-02 18:47:46 +04:00
static rb_pid_t
2020-12-05 15:05:40 +03:00
retry_fork_async_signal_safe ( struct rb_process_status * status , int * ep ,
2014-09-02 19:13:36 +04:00
int ( * chfunc ) ( void * , char * , size_t ) , void * charg ,
2018-10-30 04:34:48 +03:00
char * errmsg , size_t errmsg_buflen ,
struct waitpid_state * w )
2014-09-02 18:47:46 +04:00
{
rb_pid_t pid ;
2014-09-05 16:03:54 +04:00
volatile int try_gc = 1 ;
2014-09-06 14:27:54 +04:00
struct child_handler_disabler_state old ;
2017-11-14 07:42:38 +03:00
int err ;
2019-08-26 05:58:55 +03:00
rb_nativethread_lock_t * const volatile waitpid_lock_init =
2018-12-04 04:41:55 +03:00
( w & & WAITPID_USE_SIGCHLD ) ? & GET_VM ( ) - > waitpid_lock : 0 ;
2014-09-02 18:47:46 +04:00
while ( 1 ) {
2018-12-04 04:41:55 +03:00
rb_nativethread_lock_t * waitpid_lock = waitpid_lock_init ;
2014-09-02 18:47:46 +04:00
prefork ( ) ;
2014-09-06 14:27:54 +04:00
disable_child_handler_before_fork ( & old ) ;
2018-12-04 00:00:32 +03:00
if ( waitpid_lock ) {
rb_native_mutex_lock ( waitpid_lock ) ;
2018-10-30 04:34:48 +03:00
}
2014-09-07 05:57:44 +04:00
# ifdef HAVE_WORKING_VFORK
2014-09-04 18:56:03 +04:00
if ( ! has_privilege ( ) )
pid = vfork ( ) ;
else
2020-05-02 15:34:10 +03:00
pid = rb_fork ( ) ;
2014-09-03 07:06:17 +04:00
# else
2020-05-02 15:34:10 +03:00
pid = rb_fork ( ) ;
2018-07-26 12:32:42 +03:00
# endif
2014-09-02 19:13:36 +04:00
if ( pid = = 0 ) { /* fork succeed, child process */
int ret ;
close ( ep [ 0 ] ) ;
2014-09-06 14:27:54 +04:00
ret = disable_child_handler_fork_child ( & old , errmsg , errmsg_buflen ) ; /* async-signal-safe */
2014-09-05 16:46:09 +04:00
if ( ret = = 0 ) {
ret = chfunc ( charg , errmsg , errmsg_buflen ) ;
if ( ! ret ) _exit ( EXIT_SUCCESS ) ;
}
2014-09-02 19:13:36 +04:00
send_child_error ( ep [ 1 ] , errmsg , errmsg_buflen ) ;
# if EXIT_SUCCESS == 127
_exit ( EXIT_FAILURE ) ;
# else
_exit ( 127 ) ;
# endif
}
2021-09-21 15:02:14 +03:00
err = errno ;
2018-12-04 04:41:55 +03:00
waitpid_lock = waitpid_lock_init ;
2018-12-04 00:00:32 +03:00
if ( waitpid_lock ) {
2018-12-03 22:49:54 +03:00
if ( pid > 0 & & w ! = WAITPID_LOCK_ONLY ) {
2018-10-30 04:34:48 +03:00
w - > pid = pid ;
2018-12-04 00:00:32 +03:00
list_add ( & GET_VM ( ) - > waiting_pids , & w - > wnode ) ;
2018-10-30 04:34:48 +03:00
}
2018-12-04 00:00:32 +03:00
rb_native_mutex_unlock ( waitpid_lock ) ;
2018-10-30 04:34:48 +03:00
}
2017-11-14 07:42:38 +03:00
disable_child_handler_fork_parent ( & old ) ;
2014-09-02 18:47:46 +04:00
if ( 0 < pid ) /* fork succeed, parent process */
return pid ;
/* fork failed */
2017-11-14 07:42:38 +03:00
if ( handle_fork_error ( err , status , ep , & try_gc ) )
2014-09-02 18:47:46 +04:00
return - 1 ;
}
}
2018-10-30 04:34:48 +03:00
static rb_pid_t
2020-12-05 15:05:40 +03:00
fork_check_err ( struct rb_process_status * status , int ( * chfunc ) ( void * , char * , size_t ) , void * charg ,
2018-10-30 04:34:48 +03:00
VALUE fds , char * errmsg , size_t errmsg_buflen ,
struct rb_execarg * eargp )
2012-06-09 16:51:01 +04:00
{
rb_pid_t pid ;
2014-12-11 06:02:36 +03:00
int err ;
2012-06-09 16:51:01 +04:00
int ep [ 2 ] ;
2013-05-19 18:50:47 +04:00
int error_occurred ;
2018-10-30 04:34:48 +03:00
2020-12-05 15:05:40 +03:00
struct waitpid_state * w = eargp & & eargp - > waitpid_state ? eargp - > waitpid_state : 0 ;
2012-06-09 16:51:01 +04:00
2020-12-05 15:05:40 +03:00
if ( status ) status - > status = 0 ;
2012-06-09 16:51:01 +04:00
2014-09-02 17:56:35 +04:00
if ( pipe_nocrash ( ep , fds ) ) return - 1 ;
2020-12-05 15:05:40 +03:00
pid = retry_fork_async_signal_safe ( status , ep , chfunc , charg , errmsg , errmsg_buflen , w ) ;
if ( status ) status - > pid = pid ;
if ( pid < 0 ) {
if ( status ) status - > error = errno ;
2012-06-09 16:51:01 +04:00
return pid ;
2020-12-05 15:05:40 +03:00
}
2014-09-02 17:56:35 +04:00
close ( ep [ 1 ] ) ;
2020-12-05 15:05:40 +03:00
2014-09-02 18:27:10 +04:00
error_occurred = recv_child_error ( ep [ 0 ] , & err , errmsg , errmsg_buflen ) ;
2020-12-05 15:05:40 +03:00
2014-12-11 06:02:36 +03:00
if ( error_occurred ) {
2014-09-02 17:56:35 +04:00
if ( status ) {
2020-12-05 15:05:40 +03:00
int state = 0 ;
status - > error = err ;
2018-12-03 22:49:54 +03:00
VM_ASSERT ( ( w = = 0 | | w = = WAITPID_LOCK_ONLY ) & &
" only used by extensions " ) ;
2020-12-05 15:05:40 +03:00
rb_protect ( proc_syswait , ( VALUE ) pid , & state ) ;
status - > status = state ;
2012-06-09 16:51:01 +04:00
}
2020-05-10 10:52:54 +03:00
else if ( ! w | | w = = WAITPID_LOCK_ONLY ) {
2014-09-02 17:56:35 +04:00
rb_syswait ( pid ) ;
2012-06-09 16:51:01 +04:00
}
2020-12-05 15:05:40 +03:00
2014-09-02 17:56:35 +04:00
errno = err ;
return - 1 ;
2004-02-16 09:45:32 +03:00
}
2020-12-05 15:05:40 +03:00
2014-09-02 17:56:35 +04:00
return pid ;
2012-06-09 19:25:34 +04:00
}
2018-10-30 04:34:48 +03:00
/*
* The " async_signal_safe " name is a lie , but it is used by pty . c and
* maybe other exts . fork ( ) is not async - signal - safe due to pthread_atfork
* and future POSIX revisions will remove it from a list of signal - safe
* functions . rb_waitpid is not async - signal - safe since MJIT , either .
* For our purposes , we do not need async - signal - safety , here
*/
rb_pid_t
rb_fork_async_signal_safe ( int * status ,
int ( * chfunc ) ( void * , char * , size_t ) , void * charg ,
VALUE fds , char * errmsg , size_t errmsg_buflen )
{
2020-12-05 15:05:40 +03:00
struct rb_process_status process_status ;
rb_pid_t result = fork_check_err ( & process_status , chfunc , charg , fds , errmsg , errmsg_buflen , 0 ) ;
if ( status ) {
* status = process_status . status ;
}
return result ;
2018-10-30 04:34:48 +03:00
}
2021-10-19 10:41:09 +03:00
static rb_pid_t
rb_fork_ruby2 ( struct rb_process_status * status )
{
2014-09-02 17:56:35 +04:00
rb_pid_t pid ;
2017-11-14 07:42:38 +03:00
int try_gc = 1 , err ;
2017-09-20 21:47:14 +03:00
struct child_handler_disabler_state old ;
2014-09-02 17:56:35 +04:00
2020-12-05 15:05:40 +03:00
if ( status ) status - > status = 0 ;
2014-09-02 17:56:35 +04:00
2017-11-14 07:42:38 +03:00
while ( 1 ) {
2020-12-05 15:05:40 +03:00
prefork ( ) ;
2019-01-10 17:31:18 +03:00
if ( mjit_enabled ) mjit_pause ( false ) ; // Don't leave locked mutex to child. Note: child_handler must be enabled to pause MJIT.
2020-12-05 15:05:40 +03:00
disable_child_handler_before_fork ( & old ) ;
before_fork_ruby ( ) ;
pid = rb_fork ( ) ;
err = errno ;
2021-10-19 10:41:09 +03:00
if ( status ) {
status - > pid = pid ;
status - > error = err ;
}
2018-11-20 03:04:19 +03:00
after_fork_ruby ( ) ;
2020-12-05 15:05:40 +03:00
disable_child_handler_fork_parent ( & old ) ; /* yes, bad name */
2018-11-20 03:04:19 +03:00
if ( mjit_enabled & & pid > 0 ) mjit_resume ( ) ; /* child (pid == 0) is cared by rb_thread_atfork */
2020-12-05 15:05:40 +03:00
if ( pid > = 0 ) { /* fork succeed */
2021-07-15 10:41:54 +03:00
if ( pid = = 0 ) rb_thread_atfork ( ) ;
2020-12-05 15:05:40 +03:00
return pid ;
}
/* fork failed */
if ( handle_fork_error ( err , status , NULL , & try_gc ) ) {
return - 1 ;
2021-07-15 10:41:54 +03:00
}
2014-09-02 17:56:35 +04:00
}
2012-06-10 15:21:07 +04:00
}
2020-12-05 15:05:40 +03:00
rb_pid_t
rb_fork_ruby ( int * status )
{
struct rb_process_status process_status = { 0 } ;
rb_pid_t pid = rb_fork_ruby2 ( & process_status ) ;
if ( status ) * status = process_status . status ;
return pid ;
}
2021-10-25 14:47:19 +03:00
rb_pid_t
rb_call_proc__fork ( void )
{
VALUE pid = rb_funcall ( rb_mProcess , rb_intern ( " _fork " ) , 0 ) ;
return NUM2PIDT ( pid ) ;
}
2004-02-16 09:45:32 +03:00
# endif
2004-01-02 09:01:12 +03:00
2014-09-03 02:51:03 +04:00
# if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
2021-10-25 14:47:19 +03:00
/*
* call - seq :
* Process . _fork - > integer
*
* An internal API for fork . Do not call this method directly .
2021-12-15 01:15:02 +03:00
* Currently , this is called via Kernel # fork , Process . fork , and
* IO . popen with < tt > " - " < / tt > .
2021-10-25 14:47:19 +03:00
*
* This method is not for casual code but for application monitoring
* libraries . You can add custom code before and after fork events
* by overriding this method .
*/
VALUE
rb_proc__fork ( VALUE _obj )
{
rb_pid_t pid = rb_fork_ruby ( NULL ) ;
if ( pid = = - 1 ) {
rb_sys_fail ( " fork(2) " ) ;
}
return PIDT2NUM ( pid ) ;
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Kernel . fork [ { block } ] - > integer or nil
* Process . fork [ { block } ] - > integer or nil
2004-06-29 05:17:39 +04:00
*
2004-09-21 19:13:53 +04:00
* Creates a subprocess . If a block is specified , that block is run
* in the subprocess , and the subprocess terminates with a status of
2019-03-28 06:33:35 +03:00
* zero . Otherwise , the + fork + call returns twice , once in the
* parent , returning the process ID of the child , and once in the
* child , returning _nil_ . The child process can exit using
* Kernel . exit ! to avoid running any < code > at_exit < / code >
* functions . The parent process should use Process . wait to collect
* the termination statuses of its children or use Process . detach to
* register disinterest in their status ; otherwise , the operating
* system may accumulate zombie processes .
2005-11-20 06:30:47 +03:00
*
* The thread calling fork is the only thread in the created child process .
* fork doesn ' t copy other threads .
2010-01-24 16:20:04 +03:00
*
* If fork is not usable , Process . respond_to ? ( : fork ) returns false .
2013-06-03 06:37:34 +04:00
*
2014-02-23 06:25:59 +04:00
* Note that fork ( 2 ) is not available on some platforms like Windows and NetBSD 4.
2013-06-03 06:37:34 +04:00
* Therefore you should use spawn ( ) instead of fork ( ) .
2004-01-02 09:01:12 +03:00
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_f_fork ( VALUE obj )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t pid ;
1998-01-16 15:13:05 +03:00
2021-10-25 14:47:19 +03:00
pid = rb_call_proc__fork ( ) ;
if ( pid = = 0 ) {
2000-05-24 08:34:26 +04:00
if ( rb_block_given_p ( ) ) {
2000-11-27 12:23:38 +03:00
int status ;
2002-05-14 10:22:31 +04:00
rb_protect ( rb_yield , Qundef , & status ) ;
2000-11-27 12:23:38 +03:00
ruby_stop ( status ) ;
1998-01-16 15:13:05 +03:00
}
return Qnil ;
}
2021-10-25 14:47:19 +03:00
return PIDT2NUM ( pid ) ;
2009-04-16 18:17:14 +04:00
}
1998-01-16 15:13:05 +03:00
# else
2021-10-25 14:47:19 +03:00
# define rb_proc__fork rb_f_notimplement
2009-04-16 18:17:14 +04:00
# define rb_f_fork rb_f_notimplement
1998-01-16 15:13:05 +03:00
# endif
2004-01-02 09:01:12 +03:00
2011-12-11 05:34:42 +04:00
static int
exit_status_code ( VALUE status )
{
int istatus ;
switch ( status ) {
case Qtrue :
istatus = EXIT_SUCCESS ;
break ;
case Qfalse :
istatus = EXIT_FAILURE ;
break ;
default :
istatus = NUM2INT ( status ) ;
# if EXIT_SUCCESS != 0
if ( istatus = = 0 )
istatus = EXIT_SUCCESS ;
# endif
break ;
}
return istatus ;
}
2020-05-10 18:24:14 +03:00
NORETURN ( static VALUE rb_f_exit_bang ( int argc , VALUE * argv , VALUE obj ) ) ;
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-04-02 01:59:41 +04:00
* Process . exit ! ( status = false )
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Exits the process immediately . No exit handlers are
2010-04-02 01:59:41 +04:00
* run . < em > status < / em > is returned to the underlying system as the
2004-01-02 09:01:12 +03:00
* exit status .
2004-06-29 05:17:39 +04:00
*
2010-04-02 01:59:41 +04:00
* Process . exit ! ( true )
2004-01-02 09:01:12 +03:00
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_f_exit_bang ( int argc , VALUE * argv , VALUE obj )
1998-01-16 15:13:05 +03:00
{
1999-08-13 09:45:20 +04:00
int istatus ;
1998-01-16 15:13:05 +03:00
2016-04-14 07:41:47 +03:00
if ( rb_check_arity ( argc , 0 , 1 ) = = 1 ) {
istatus = exit_status_code ( argv [ 0 ] ) ;
1999-08-13 09:45:20 +04:00
}
else {
2003-10-13 17:05:24 +04:00
istatus = EXIT_FAILURE ;
1998-01-16 15:13:05 +03:00
}
1999-08-13 09:45:20 +04:00
_exit ( istatus ) ;
2000-03-07 11:37:59 +03:00
2018-07-24 08:38:07 +03:00
UNREACHABLE_RETURN ( Qnil ) ;
1998-01-16 15:13:05 +03:00
}
2007-08-18 11:44:51 +04:00
void
rb_exit ( int status )
{
2017-10-26 17:44:09 +03:00
if ( GET_EC ( ) - > tag ) {
2007-08-18 11:44:51 +04:00
VALUE args [ 2 ] ;
args [ 0 ] = INT2NUM ( status ) ;
args [ 1 ] = rb_str_new2 ( " exit " ) ;
rb_exc_raise ( rb_class_new_instance ( 2 , args , rb_eSystemExit ) ) ;
}
2014-05-10 08:41:02 +04:00
ruby_stop ( status ) ;
2007-08-18 11:44:51 +04:00
}
2019-08-29 04:23:14 +03:00
VALUE
rb_f_exit ( int argc , const VALUE * argv )
{
int istatus ;
if ( rb_check_arity ( argc , 0 , 1 ) = = 1 ) {
istatus = exit_status_code ( argv [ 0 ] ) ;
}
else {
istatus = EXIT_SUCCESS ;
}
rb_exit ( istatus ) ;
UNREACHABLE_RETURN ( Qnil ) ;
}
2007-08-18 11:44:51 +04:00
2020-05-10 18:24:14 +03:00
NORETURN ( static VALUE f_exit ( int c , const VALUE * a , VALUE _ ) ) ;
2007-08-18 11:44:51 +04:00
/*
* call - seq :
2010-04-02 01:59:41 +04:00
* exit ( status = true )
* Kernel : : exit ( status = true )
* Process : : exit ( status = true )
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* Initiates the termination of the Ruby script by raising the
2019-03-28 06:33:35 +03:00
* SystemExit exception . This exception may be caught . The
2007-08-18 11:44:51 +04:00
* optional parameter is used to return a status code to the invoking
* environment .
2010-04-02 01:59:41 +04:00
* + true + and + FALSE + of _status_ means success and failure
* respectively . The interpretation of other integer values are
* system dependent .
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* begin
* exit
* puts " never get here "
* rescue SystemExit
* puts " rescued a SystemExit exception "
* end
* puts " after begin block "
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* < em > produces : < / em >
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* rescued a SystemExit exception
* after begin block
2009-02-06 15:54:52 +03:00
*
2019-03-28 06:33:35 +03:00
* Just prior to termination , Ruby executes any < code > at_exit < / code >
* functions ( see Kernel : : at_exit ) and runs any object finalizers
* ( see ObjectSpace : : define_finalizer ) .
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* at_exit { puts " at_exit function " }
* ObjectSpace . define_finalizer ( " string " , proc { puts " in finalizer " } )
* exit
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* < em > produces : < / em >
2009-02-06 15:54:52 +03:00
*
2007-08-18 11:44:51 +04:00
* at_exit function
* in finalizer
*/
2019-08-28 12:19:11 +03:00
static VALUE
f_exit ( int c , const VALUE * a , VALUE _ )
{
2020-05-10 18:24:14 +03:00
rb_f_exit ( c , a ) ;
UNREACHABLE_RETURN ( Qnil ) ;
2019-08-28 12:19:11 +03:00
}
2007-08-18 11:44:51 +04:00
VALUE
2014-06-18 10:16:39 +04:00
rb_f_abort ( int argc , const VALUE * argv )
2007-08-18 11:44:51 +04:00
{
2014-06-18 10:16:39 +04:00
rb_check_arity ( argc , 0 , 1 ) ;
2007-08-18 11:44:51 +04:00
if ( argc = = 0 ) {
2017-10-29 17:06:58 +03:00
rb_execution_context_t * ec = GET_EC ( ) ;
2019-12-16 03:44:01 +03:00
VALUE errinfo = rb_ec_get_errinfo ( ec ) ;
2017-06-16 04:53:15 +03:00
if ( ! NIL_P ( errinfo ) ) {
2017-10-29 17:06:58 +03:00
rb_ec_error_print ( ec , errinfo ) ;
2007-08-18 11:44:51 +04:00
}
rb_exit ( EXIT_FAILURE ) ;
}
else {
VALUE args [ 2 ] ;
2014-06-18 10:16:39 +04:00
args [ 1 ] = args [ 0 ] = argv [ 0 ] ;
StringValue ( args [ 0 ] ) ;
2020-03-09 20:22:11 +03:00
rb_io_puts ( 1 , args , rb_ractor_stderr ( ) ) ;
2007-08-18 11:44:51 +04:00
args [ 0 ] = INT2NUM ( EXIT_FAILURE ) ;
rb_exc_raise ( rb_class_new_instance ( 2 , args , rb_eSystemExit ) ) ;
}
2012-04-14 04:36:26 +04:00
2018-07-24 08:38:07 +03:00
UNREACHABLE_RETURN ( Qnil ) ;
2007-08-18 11:44:51 +04:00
}
2020-05-10 18:24:14 +03:00
NORETURN ( static VALUE f_abort ( int c , const VALUE * a , VALUE _ ) ) ;
2020-12-11 08:09:34 +03:00
/*
* call - seq :
* abort
* Kernel : : abort ( [ msg ] )
* Process . abort ( [ msg ] )
*
* Terminate execution immediately , effectively by calling
* < code > Kernel . exit ( false ) < / code > . If _msg_ is given , it is written
* to STDERR prior to terminating .
*/
2019-08-28 12:19:11 +03:00
static VALUE
f_abort ( int c , const VALUE * a , VALUE _ )
{
2020-05-10 18:24:14 +03:00
rb_f_abort ( c , a ) ;
UNREACHABLE_RETURN ( Qnil ) ;
2019-08-28 12:19:11 +03:00
}
1998-01-16 15:13:05 +03:00
void
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_syswait ( rb_pid_t pid )
1998-01-16 15:13:05 +03:00
{
int status ;
2011-07-10 21:04:40 +04:00
rb_waitpid ( pid , & status , 0 ) ;
1998-01-16 15:13:05 +03:00
}
2021-08-16 11:00:19 +03:00
# if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV && !defined __EMSCRIPTEN__
2016-05-20 18:36:34 +03:00
char *
rb_execarg_commandline ( const struct rb_execarg * eargp , VALUE * prog )
{
VALUE cmd = * prog ;
if ( eargp & & ! eargp - > use_shell ) {
VALUE str = eargp - > invoke . cmd . argv_str ;
VALUE buf = eargp - > invoke . cmd . argv_buf ;
char * p , * * argv = ARGVSTR2ARGV ( str ) ;
long i , argc = ARGVSTR2ARGC ( str ) ;
const char * start = RSTRING_PTR ( buf ) ;
cmd = rb_str_new ( start , RSTRING_LEN ( buf ) ) ;
p = RSTRING_PTR ( cmd ) ;
for ( i = 1 ; i < argc ; + + i ) {
p [ argv [ i ] - start - 1 ] = ' ' ;
}
* prog = cmd ;
return p ;
}
return StringValueCStr ( * prog ) ;
}
# endif
2008-04-25 19:50:24 +04:00
static rb_pid_t
2012-06-23 03:09:16 +04:00
rb_spawn_process ( struct rb_execarg * eargp , char * errmsg , size_t errmsg_buflen )
2004-02-16 09:45:32 +03:00
{
2009-03-14 08:46:43 +03:00
rb_pid_t pid ;
2014-09-03 02:51:03 +04:00
# if !defined HAVE_WORKING_FORK || USE_SPAWNV
2012-06-05 23:59:43 +04:00
VALUE prog ;
2012-06-20 15:46:50 +04:00
struct rb_execarg sarg ;
2016-05-20 18:36:34 +03:00
# if !defined HAVE_SPAWNV
int status ;
# endif
2008-05-12 18:15:32 +04:00
# endif
2008-04-28 04:11:46 +04:00
2014-09-03 02:51:03 +04:00
# if defined HAVE_WORKING_FORK && !USE_SPAWNV
2020-12-05 15:05:40 +03:00
pid = fork_check_err ( eargp - > status , rb_exec_atfork , eargp , eargp - > redirect_fds , errmsg , errmsg_buflen , eargp ) ;
2008-05-12 13:17:58 +04:00
# else
2012-06-23 03:09:16 +04:00
prog = eargp - > use_shell ? eargp - > invoke . sh . shell_script : eargp - > invoke . cmd . command_name ;
2012-06-05 23:59:43 +04:00
2012-06-23 03:09:16 +04:00
if ( rb_execarg_run_options ( eargp , & sarg , errmsg , errmsg_buflen ) < 0 ) {
2008-05-12 13:17:58 +04:00
return - 1 ;
}
2012-06-23 03:09:16 +04:00
if ( prog & & ! eargp - > use_shell ) {
char * * argv = ARGVSTR2ARGV ( eargp - > invoke . cmd . argv_str ) ;
2012-06-04 05:44:27 +04:00
argv [ 0 ] = RSTRING_PTR ( prog ) ;
2012-06-03 19:45:46 +04:00
}
2008-05-12 13:17:58 +04:00
# if defined HAVE_SPAWNV
2012-06-23 03:09:16 +04:00
if ( eargp - > use_shell ) {
2020-12-07 23:29:09 +03:00
pid = proc_spawn_sh ( RSTRING_PTR ( prog ) ) ;
2004-02-16 09:45:32 +03:00
}
else {
2012-06-23 03:09:16 +04:00
char * * argv = ARGVSTR2ARGV ( eargp - > invoke . cmd . argv_str ) ;
2020-12-07 23:29:09 +03:00
pid = proc_spawn_cmd ( argv , prog , eargp ) ;
}
if ( pid = = - 1 ) {
2020-12-09 05:49:20 +03:00
rb_last_status_set ( 0x7f < < 8 , pid ) ;
2004-02-16 09:45:32 +03:00
}
2008-05-12 13:17:58 +04:00
# else
2016-05-20 18:36:34 +03:00
status = system ( rb_execarg_commandline ( eargp , & prog ) ) ;
2014-12-26 09:09:11 +03:00
pid = 1 ; /* dummy */
2020-12-09 05:49:20 +03:00
rb_last_status_set ( ( status & 0xff ) < < 8 , pid ) ;
2004-02-16 09:45:32 +03:00
# endif
2020-12-07 23:29:09 +03:00
2018-12-03 22:49:54 +03:00
if ( eargp - > waitpid_state & & eargp - > waitpid_state ! = WAITPID_LOCK_ONLY ) {
2018-10-30 04:34:48 +03:00
eargp - > waitpid_state - > pid = pid ;
}
2020-12-07 23:29:09 +03:00
2012-06-21 14:48:48 +04:00
rb_execarg_run_options ( & sarg , NULL , errmsg , errmsg_buflen ) ;
2004-02-16 09:45:32 +03:00
# endif
2020-12-07 23:29:09 +03:00
2009-03-14 08:46:43 +03:00
return pid ;
2004-02-16 09:45:32 +03:00
}
2015-05-22 13:42:09 +03:00
struct spawn_args {
VALUE execarg ;
struct {
2020-12-07 23:29:09 +03:00
char * ptr ;
size_t buflen ;
2015-05-22 13:42:09 +03:00
} errmsg ;
} ;
static VALUE
do_spawn_process ( VALUE arg )
{
struct spawn_args * argp = ( struct spawn_args * ) arg ;
rb_execarg_parent_start1 ( argp - > execarg ) ;
return ( VALUE ) rb_spawn_process ( DATA_PTR ( argp - > execarg ) ,
argp - > errmsg . ptr , argp - > errmsg . buflen ) ;
}
static rb_pid_t
rb_execarg_spawn ( VALUE execarg_obj , char * errmsg , size_t errmsg_buflen )
{
struct spawn_args args ;
2018-12-03 22:49:54 +03:00
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
/*
* Prevent a race with MJIT where the compiler process where
* can hold an FD of ours in between vfork + execve
*/
if ( ! eargp - > waitpid_state & & mjit_enabled ) {
eargp - > waitpid_state = WAITPID_LOCK_ONLY ;
}
2015-05-22 13:42:09 +03:00
args . execarg = execarg_obj ;
args . errmsg . ptr = errmsg ;
args . errmsg . buflen = errmsg_buflen ;
return ( rb_pid_t ) rb_ensure ( do_spawn_process , ( VALUE ) & args ,
execarg_parent_end , execarg_obj ) ;
}
2010-05-24 03:16:09 +04:00
static rb_pid_t
2014-06-18 10:16:39 +04:00
rb_spawn_internal ( int argc , const VALUE * argv , char * errmsg , size_t errmsg_buflen )
2010-05-24 03:16:09 +04:00
{
2012-06-20 14:31:02 +04:00
VALUE execarg_obj ;
2018-01-24 17:11:25 +03:00
execarg_obj = rb_execarg_new ( argc , argv , TRUE , FALSE ) ;
2015-05-22 13:42:09 +03:00
return rb_execarg_spawn ( execarg_obj , errmsg , errmsg_buflen ) ;
2010-05-24 03:16:09 +04:00
}
2008-04-25 19:50:24 +04:00
rb_pid_t
2014-06-18 10:16:39 +04:00
rb_spawn_err ( int argc , const VALUE * argv , char * errmsg , size_t errmsg_buflen )
2008-04-25 19:50:24 +04:00
{
2012-06-09 05:07:07 +04:00
return rb_spawn_internal ( argc , argv , errmsg , errmsg_buflen ) ;
2008-04-25 19:50:24 +04:00
}
2009-02-05 14:33:19 +03:00
rb_pid_t
2014-06-18 10:16:39 +04:00
rb_spawn ( int argc , const VALUE * argv )
2009-02-05 14:33:19 +03:00
{
2012-06-09 05:07:07 +04:00
return rb_spawn_internal ( argc , argv , NULL , 0 ) ;
2009-02-05 14:33:19 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2018-12-29 14:04:42 +03:00
* system ( [ env , ] command . . . [ , options ] , exception : false ) - > true , false or nil
2008-12-05 18:09:59 +03:00
*
* Executes _command . . . _ in a subshell .
* _command . . . _ is one of following forms .
2004-06-29 05:17:39 +04:00
*
2022-02-18 15:46:04 +03:00
* This method has potential security vulnerabilities if called with untrusted input ;
* see { Command Injection } [ command_injection . rdoc ] .
*
2018-12-29 14:04:42 +03:00
* [ < code > commandline < / code > ]
* command line string which is passed to the standard shell
* [ < code > cmdname , arg1 , . . . < / code > ]
* command name and one or more arguments ( no shell )
* [ < code > [ cmdname , argv0 ] , arg1 , . . . < / code > ]
* command name , < code > argv [ 0 ] < / code > and zero or more arguments ( no shell )
2008-12-05 18:09:59 +03:00
*
* system returns + true + if the command gives zero exit status ,
* + false + for non zero exit status .
* Returns + nil + if command execution fails .
* An error status is available in < code > $ ? < / code > .
2018-12-29 14:04:42 +03:00
*
2019-01-20 18:07:17 +03:00
* If the < code > exception : true < / code > argument is passed , the method
* raises an exception instead of returning + false + or + nil + .
2018-12-29 14:04:42 +03:00
*
2008-12-05 18:09:59 +03:00
* The arguments are processed in the same way as
2018-12-29 14:04:42 +03:00
* for Kernel # spawn .
2004-06-29 05:17:39 +04:00
*
2019-03-28 06:33:35 +03:00
* The hash arguments , env and options , are same as # exec and # spawn .
2018-12-29 14:04:42 +03:00
* See Kernel # spawn for details .
2008-04-24 18:46:39 +04:00
*
2004-01-02 09:01:12 +03:00
* system ( " echo * " )
* system ( " echo " , " * " )
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* < em > produces : < / em >
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* config . h main . rb
* *
2009-11-10 02:23:23 +03:00
*
2019-01-20 18:07:17 +03:00
* Error handling :
2018-12-29 14:04:42 +03:00
*
* system ( " cat nonexistent.txt " )
* # = > false
* system ( " catt nonexistent.txt " )
* # = > nil
*
* system ( " cat nonexistent.txt " , exception : true )
* # RuntimeError ( Command failed with exit 1 : cat )
* system ( " catt nonexistent.txt " , exception : true )
* # Errno : : ENOENT ( No such file or directory - catt )
*
* See Kernel # exec for the standard shell .
2004-01-02 09:01:12 +03:00
*/
1998-01-16 15:13:05 +03:00
static VALUE
2019-08-28 12:19:11 +03:00
rb_f_system ( int argc , VALUE * argv , VALUE _ )
1998-01-16 15:13:05 +03:00
{
2020-12-05 15:05:40 +03:00
VALUE execarg_obj = rb_execarg_new ( argc , argv , TRUE , TRUE ) ;
struct rb_execarg * eargp = rb_execarg_get ( execarg_obj ) ;
2007-12-23 18:39:09 +03:00
2021-09-21 15:02:14 +03:00
struct rb_process_status status = { 0 } ;
2020-12-05 15:05:40 +03:00
eargp - > status = & status ;
rb_last_status_clear ( ) ;
2021-09-21 15:02:14 +03:00
// This function can set the thread's last status.
// May be different from waitpid_state.pid on exec failure.
rb_pid_t pid = rb_execarg_spawn ( execarg_obj , 0 , 0 ) ;
2020-12-05 15:05:40 +03:00
if ( pid > 0 ) {
VALUE status = rb_process_status_wait ( pid , 0 ) ;
struct rb_process_status * data = RTYPEDDATA_DATA ( status ) ;
// Set the last status:
rb_obj_freeze ( status ) ;
GET_THREAD ( ) - > last_status = status ;
if ( data - > status = = EXIT_SUCCESS ) {
return Qtrue ;
2018-07-08 03:02:27 +03:00
}
2020-12-05 15:05:40 +03:00
if ( data - > error ! = 0 ) {
if ( eargp - > exception ) {
VALUE command = eargp - > invoke . sh . shell_script ;
RB_GC_GUARD ( execarg_obj ) ;
rb_syserr_fail_str ( data - > error , command ) ;
}
else {
return Qnil ;
}
2018-10-30 04:34:48 +03:00
}
2020-12-05 15:05:40 +03:00
else if ( eargp - > exception ) {
2018-02-25 06:08:40 +03:00
VALUE command = eargp - > invoke . sh . shell_script ;
2020-12-05 15:05:40 +03:00
VALUE str = rb_str_new_cstr ( " Command failed with " ) ;
rb_str_cat_cstr ( pst_message_status ( str , data - > status ) , " : " ) ;
rb_str_append ( str , command ) ;
2018-01-24 17:11:25 +03:00
RB_GC_GUARD ( execarg_obj ) ;
2020-12-05 15:05:40 +03:00
rb_exc_raise ( rb_exc_new_str ( rb_eRuntimeError , str ) ) ;
2018-01-24 17:11:25 +03:00
}
else {
2020-12-05 15:05:40 +03:00
return Qfalse ;
2018-01-24 17:11:25 +03:00
}
2020-12-05 15:05:40 +03:00
RB_GC_GUARD ( status ) ;
2006-07-18 18:36:15 +04:00
}
2020-12-05 15:05:40 +03:00
2018-01-24 17:11:25 +03:00
if ( eargp - > exception ) {
2018-02-25 06:08:40 +03:00
VALUE command = eargp - > invoke . sh . shell_script ;
2018-02-25 05:12:25 +03:00
RB_GC_GUARD ( execarg_obj ) ;
2020-12-05 15:05:40 +03:00
rb_syserr_fail_str ( errno , command ) ;
2018-01-24 17:11:25 +03:00
}
else {
2020-12-05 15:05:40 +03:00
return Qnil ;
2018-01-24 17:11:25 +03:00
}
2004-02-16 09:45:32 +03:00
}
2002-03-22 10:26:42 +03:00
2004-02-16 09:45:32 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* spawn ( [ env , ] command . . . [ , options ] ) - > pid
* Process . spawn ( [ env , ] command . . . [ , options ] ) - > pid
2008-12-04 14:45:54 +03:00
*
* spawn executes specified command and return its pid .
2009-08-11 17:27:46 +04:00
*
2013-05-30 07:57:46 +04:00
* pid = spawn ( " tar xf ruby-2.0.0-p195.tar.bz2 " )
* Process . wait pid
*
2013-06-03 06:37:34 +04:00
* pid = spawn ( RbConfig . ruby , " -eputs'Hello, world!' " )
* Process . wait pid
*
2013-05-30 12:55:41 +04:00
* This method is similar to Kernel # system but it doesn ' t wait for the command
* to finish .
*
2009-08-11 17:27:46 +04:00
* The parent process should
2019-03-28 06:33:35 +03:00
* use Process . wait to collect
2009-08-11 17:27:46 +04:00
* the termination status of its child or
2019-03-28 06:33:35 +03:00
* use Process . detach to register
2009-08-11 17:27:46 +04:00
* disinterest in their status ;
* otherwise , the operating system may accumulate zombie processes .
2008-12-04 14:45:54 +03:00
*
* spawn has bunch of options to specify process attributes :
*
* env : hash
* name = > val : set the environment variable
* name = > nil : unset the environment variable
2015-02-18 05:42:58 +03:00
*
2015-08-19 17:55:32 +03:00
* the keys and the values except for + nil + must be strings .
2008-12-04 14:45:54 +03:00
* command . . . :
2009-11-10 02:23:23 +03:00
* commandline : command line string which is passed to the standard shell
2013-08-05 20:42:37 +04:00
* cmdname , arg1 , . . . : command name and one or more arguments ( This form does not use the shell . See below for caveats . )
2009-02-22 17:38:05 +03:00
* [ cmdname , argv0 ] , arg1 , . . . : command name , argv [ 0 ] and zero or more arguments ( no shell )
2008-12-04 14:45:54 +03:00
* options : hash
* clearing environment variables :
* : unsetenv_others = > true : clear environment variables except specified by env
* : unsetenv_others = > false : don ' t clear ( default )
* process group :
2009-02-22 17:38:05 +03:00
* : pgroup = > true or 0 : make a new process group
2015-09-10 16:15:55 +03:00
* : pgroup = > pgid : join the specified process group
2009-04-18 13:06:34 +04:00
* : pgroup = > nil : don ' t change the process group ( default )
2012-04-07 18:10:30 +04:00
* create new process group : Windows only
* : new_pgroup = > true : the new process is the root process of a new process group
* : new_pgroup = > false : don ' t create a new process group ( default )
2008-12-04 18:21:32 +03:00
* resource limit : resourcename is core , cpu , data , etc . See Process . setrlimit .
* : rlimit_resourcename = > limit
* : rlimit_resourcename = > [ cur_limit , max_limit ]
2008-12-04 14:45:54 +03:00
* umask :
* : umask = > int
* redirection :
* key :
* FD : single file descriptor in child process
* [ FD , FD , . . . ] : multiple file descriptor in child process
* value :
* FD : redirect to the file descriptor in parent process
* string : redirect to file with open ( string , " r " or " w " )
* [ string ] : redirect to file with open ( string , File : : RDONLY )
* [ string , open_mode ] : redirect to file with open ( string , open_mode , 0644 )
* [ string , open_mode , perm ] : redirect to file with open ( string , open_mode , perm )
* [ : child , FD ] : redirect to the redirected file descriptor
* : close : close the file descriptor in child process
* FD is one of follows
2009-03-31 22:49:25 +04:00
* : in : the file descriptor 0 which is the standard input
* : out : the file descriptor 1 which is the standard output
* : err : the file descriptor 2 which is the standard error
2008-12-04 14:45:54 +03:00
* integer : the file descriptor of specified the integer
* io : the file descriptor specified as io . fileno
* file descriptor inheritance : close non - redirected non - standard fds ( 3 , 4 , 5 , . . . ) or not
2018-08-17 02:56:08 +03:00
* : close_others = > false : inherit
2012-03-03 17:53:53 +04:00
* current directory :
* : chdir = > str
2008-04-24 18:46:39 +04:00
*
2019-03-30 15:37:23 +03:00
* The < code > cmdname , arg1 , . . . < / code > form does not use the shell .
2019-03-29 04:26:23 +03:00
* However , on different OSes , different things are provided as
* built - in commands . An example of this is + ' echo ' + , which is a
* built - in on Windows , but is a normal program on Linux and Mac OS X .
* This means that < code > Process . spawn ' echo ' , ' % Path % ' < / code > will
* display the contents of the < tt > % Path % < / tt > environment variable
* on Windows , but < code > Process . spawn ' echo ' , ' $ PATH ' < / code > prints
* the literal < tt > $ PATH < / tt > .
2013-08-05 20:42:37 +04:00
*
2008-04-24 18:46:39 +04:00
* If a hash is given as + env + , the environment is
* updated by + env + before < code > exec ( 2 ) < / code > in the child process .
2008-07-05 16:25:33 +04:00
* If a pair in + env + has nil as the value , the variable is deleted .
*
* # set FOO as BAR and unset BAZ .
* pid = spawn ( { " FOO " = > " BAR " , " BAZ " = > nil } , command )
2008-04-24 18:46:39 +04:00
*
* If a hash is given as + options + ,
* it specifies
* process group ,
2012-04-07 18:10:30 +04:00
* create new process group ,
2009-02-06 15:54:52 +03:00
* resource limit ,
2008-04-24 18:46:39 +04:00
* current directory ,
* umask and
* redirects for the child process .
* Also , it can be specified to clear environment variables .
*
* The < code > : unsetenv_others < / code > key in + options + specifies
* to clear environment variables , other than specified by + env + .
*
* pid = spawn ( command , : unsetenv_others = > true ) # no environment variable
* pid = spawn ( { " FOO " = > " BAR " } , command , : unsetenv_others = > true ) # FOO only
*
* The < code > : pgroup < / code > key in + options + specifies a process group .
2015-09-10 16:15:55 +03:00
* The corresponding value should be true , zero , a positive integer , or nil .
* true and zero cause the process to be a process leader of a new process group .
* A non - zero positive integer causes the process to join the provided process group .
* The default value , nil , causes the process to remain in the same process group .
2008-04-24 18:46:39 +04:00
*
* pid = spawn ( command , : pgroup = > true ) # process leader
* pid = spawn ( command , : pgroup = > 10 ) # belongs to the process group 10
*
2012-04-07 18:10:30 +04:00
* The < code > : new_pgroup < / code > key in + options + specifies to pass
* + CREATE_NEW_PROCESS_GROUP + flag to < code > CreateProcessW ( ) < / code > that is
* Windows API . This option is only for Windows .
* true means the new process is the root process of the new process group .
* The new process has CTRL + C disabled . This flag is necessary for
* < code > Process . kill ( : SIGINT , pid ) < / code > on the subprocess .
* : new_pgroup is false by default .
*
* pid = spawn ( command , : new_pgroup = > true ) # new process group
* pid = spawn ( command , : new_pgroup = > false ) # same process group
*
2008-04-24 18:46:39 +04:00
* The < code > : rlimit_ < / code > < em > foo < / em > key specifies a resource limit .
2009-02-22 17:38:05 +03:00
* < em > foo < / em > should be one of resource types such as < code > core < / code > .
2008-04-24 18:46:39 +04:00
* The corresponding value should be an integer or an array which have one or
* two integers : same as cur_limit and max_limit arguments for
* Process . setrlimit .
*
* cur , max = Process . getrlimit ( : CORE )
* pid = spawn ( command , : rlimit_core = > [ 0 , max ] ) # disable core temporary .
* pid = spawn ( command , : rlimit_core = > max ) # enable core dump
2009-03-31 22:49:25 +04:00
* pid = spawn ( command , : rlimit_core = > 0 ) # never dump core .
2008-04-24 18:46:39 +04:00
*
* The < code > : umask < / code > key in + options + specifies the umask .
*
* pid = spawn ( command , : umask = > 077 )
*
2016-09-24 05:28:25 +03:00
* The : in , : out , : err , an integer , an IO and an array key specifies a redirection .
2008-04-24 18:46:39 +04:00
* The redirection maps a file descriptor in the child process .
*
2008-12-03 18:02:10 +03:00
* For example , stderr can be merged into stdout as follows :
2008-04-24 18:46:39 +04:00
*
2008-12-03 18:02:10 +03:00
* pid = spawn ( command , : err = > : out )
2008-04-24 18:46:39 +04:00
* pid = spawn ( command , 2 = > 1 )
2008-12-03 18:02:10 +03:00
* pid = spawn ( command , STDERR = > : out )
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , STDERR = > STDOUT )
2008-04-24 18:46:39 +04:00
*
2019-03-28 06:33:35 +03:00
* The hash keys specifies a file descriptor in the child process
* started by # spawn .
2008-12-05 13:00:36 +03:00
* : err , 2 and STDERR specifies the standard error stream ( stderr ) .
2008-04-24 18:46:39 +04:00
*
2019-03-28 06:33:35 +03:00
* The hash values specifies a file descriptor in the parent process
* which invokes # spawn .
2008-12-05 13:00:36 +03:00
* : out , 1 and STDOUT specifies the standard output stream ( stdout ) .
2008-04-24 18:46:39 +04:00
*
2008-12-03 18:02:10 +03:00
* In the above example ,
* the standard output in the child process is not specified .
2008-04-24 18:46:39 +04:00
* So it is inherited from the parent process .
*
2009-02-22 17:38:05 +03:00
* The standard input stream ( stdin ) can be specified by : in , 0 and STDIN .
2009-02-06 15:54:52 +03:00
*
2008-04-24 18:46:39 +04:00
* A filename can be specified as a hash value .
*
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , : in = > " /dev/null " ) # read mode
* pid = spawn ( command , : out = > " /dev/null " ) # write mode
* pid = spawn ( command , : err = > " log " ) # write mode
2014-05-09 17:57:04 +04:00
* pid = spawn ( command , [ : out , : err ] = > " /dev/null " ) # write mode
2008-04-24 18:46:39 +04:00
* pid = spawn ( command , 3 = > " /dev/null " ) # read mode
*
2014-05-09 17:57:04 +04:00
* For stdout and stderr ( and combination of them ) ,
2008-04-24 18:46:39 +04:00
* it is opened in write mode .
* Otherwise read mode is used .
*
* For specifying flags and permission of file creation explicitly ,
* an array is used instead .
*
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , : in = > [ " file " ] ) # read mode is assumed
* pid = spawn ( command , : in = > [ " file " , " r " ] )
* pid = spawn ( command , : out = > [ " log " , " w " ] ) # 0644 assumed
* pid = spawn ( command , : out = > [ " log " , " w " , 0600 ] )
* pid = spawn ( command , : out = > [ " log " , File : : WRONLY | File : : EXCL | File : : CREAT , 0600 ] )
2008-04-24 18:46:39 +04:00
*
* The array specifies a filename , flags and permission .
* The flags can be a string or an integer .
2009-02-22 17:38:05 +03:00
* If the flags is omitted or nil , File : : RDONLY is assumed .
2008-04-24 18:46:39 +04:00
* The permission should be an integer .
2009-02-22 17:38:05 +03:00
* If the permission is omitted or nil , 0644 is assumed .
2008-04-24 18:46:39 +04:00
*
* If an array of IOs and integers are specified as a hash key ,
2009-02-22 17:38:05 +03:00
* all the elements are redirected .
2008-04-24 18:46:39 +04:00
*
2008-12-05 13:00:36 +03:00
* # stdout and stderr is redirected to log file .
2008-12-03 18:02:10 +03:00
* # The file " log " is opened just once .
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , [ : out , : err ] = > [ " log " , " w " ] )
2008-04-24 18:46:39 +04:00
*
2008-12-03 18:02:10 +03:00
* Another way to merge multiple file descriptors is [ : child , fd ] .
2009-02-22 17:38:05 +03:00
* \ [ : child , fd ] means the file descriptor in the child process .
2008-12-03 18:02:10 +03:00
* This is different from fd .
2008-12-05 13:00:36 +03:00
* For example , : err = > : out means redirecting child stderr to parent stdout .
* But : err = > [ : child , : out ] means redirecting child stderr to child stdout .
2012-01-03 10:53:49 +04:00
* They differ if stdout is redirected in the child process as follows .
2008-12-03 18:02:10 +03:00
*
2008-12-05 13:00:36 +03:00
* # stdout and stderr is redirected to log file .
2008-12-03 18:02:10 +03:00
* # The file " log " is opened just once .
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , : out = > [ " log " , " w " ] , : err = > [ : child , : out ] )
2008-12-03 18:02:10 +03:00
*
2009-02-22 17:38:05 +03:00
* \ [ : child , : out ] can be used to merge stderr into stdout in IO . popen .
2008-12-05 13:00:36 +03:00
* In this case , IO . popen redirects stdout to a pipe in the child process
* and [ : child , : out ] refers the redirected stdout .
2008-12-03 18:02:10 +03:00
*
2008-12-05 13:00:36 +03:00
* io = IO . popen ( [ " sh " , " -c " , " echo out; echo err >&2 " , : err = > [ : child , : out ] ] )
2008-12-03 18:02:10 +03:00
* p io . read # = > " out \n err \n "
*
2012-03-03 17:53:53 +04:00
* The < code > : chdir < / code > key in + options + specifies the current directory .
*
* pid = spawn ( command , : chdir = > " /var/tmp " )
*
2008-04-25 21:01:57 +04:00
* spawn closes all non - standard unspecified descriptors by default .
* The " standard " descriptors are 0 , 1 and 2.
* This behavior is specified by : close_others option .
2008-04-30 09:40:19 +04:00
* : close_others doesn ' t affect the standard descriptors which are
* closed only if : close is specified explicitly .
2008-04-24 18:46:39 +04:00
*
2008-04-25 21:01:57 +04:00
* pid = spawn ( command , : close_others = > true ) # close 3 , 4 , 5 , . . . ( default )
* pid = spawn ( command , : close_others = > false ) # don ' t close 3 , 4 , 5 , . . .
2008-04-24 18:46:39 +04:00
*
2018-08-17 02:56:08 +03:00
* : close_others is false by default for spawn and IO . popen .
2008-04-24 18:46:39 +04:00
*
2012-06-28 14:38:26 +04:00
* Note that fds which close - on - exec flag is already set are closed
* regardless of : close_others option .
*
2008-04-25 21:01:57 +04:00
* So IO . pipe and spawn can be used as IO . popen .
*
* # similar to r = IO . popen ( command )
2008-04-24 18:46:39 +04:00
* r , w = IO . pipe
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , : out = > w ) # r , w is closed in the child process .
2008-04-24 18:46:39 +04:00
* w . close
*
2009-02-22 17:38:05 +03:00
* : close is specified as a hash value to close a fd individually .
2008-04-25 21:01:57 +04:00
*
* f = open ( foo )
* system ( command , f = > : close ) # don ' t inherit f .
*
2008-12-05 13:00:36 +03:00
* If a file descriptor need to be inherited ,
* io = > io can be used .
*
* # valgrind has - - log - fd option for log destination .
* # log_w = > log_w indicates log_w . fileno inherits to child process .
* log_r , log_w = IO . pipe
* pid = spawn ( " valgrind " , " --log-fd=#{log_w.fileno} " , " echo " , " a " , log_w = > log_w )
* log_w . close
* p log_r . read
*
2008-04-24 18:46:39 +04:00
* It is also possible to exchange file descriptors .
*
2008-12-05 13:00:36 +03:00
* pid = spawn ( command , : out = > : err , : err = > : out )
2008-04-24 18:46:39 +04:00
*
* The hash keys specify file descriptors in the child process .
* The hash values specifies file descriptors in the parent process .
2008-12-05 13:00:36 +03:00
* So the above specifies exchanging stdout and stderr .
2008-04-24 18:46:39 +04:00
* Internally , + spawn + uses an extra file descriptor to resolve such cyclic
* file descriptor mapping .
*
2019-03-28 06:33:35 +03:00
* See Kernel . exec for the standard shell .
2004-02-16 09:45:32 +03:00
*/
2002-03-22 10:26:42 +03:00
2004-02-16 09:45:32 +03:00
static VALUE
2019-08-28 12:19:11 +03:00
rb_f_spawn ( int argc , VALUE * argv , VALUE _ )
2004-02-16 09:45:32 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t pid ;
2008-12-23 16:15:54 +03:00
char errmsg [ CHILD_ERRMSG_BUFLEN ] = { ' \0 ' } ;
2012-06-20 14:31:02 +04:00
VALUE execarg_obj , fail_str ;
2012-06-23 03:09:16 +04:00
struct rb_execarg * eargp ;
2012-06-20 14:31:02 +04:00
2018-01-24 17:11:25 +03:00
execarg_obj = rb_execarg_new ( argc , argv , TRUE , FALSE ) ;
2012-06-23 03:09:16 +04:00
eargp = rb_execarg_get ( execarg_obj ) ;
fail_str = eargp - > use_shell ? eargp - > invoke . sh . shell_script : eargp - > invoke . cmd . command_name ;
2012-06-20 14:31:02 +04:00
2015-05-22 13:42:09 +03:00
pid = rb_execarg_spawn ( execarg_obj , errmsg , sizeof ( errmsg ) ) ;
1998-01-16 15:13:05 +03:00
2008-12-23 16:15:54 +03:00
if ( pid = = - 1 ) {
2015-09-07 17:45:31 +03:00
int err = errno ;
rb_exec_fail ( eargp , err , errmsg ) ;
RB_GC_GUARD ( execarg_obj ) ;
rb_syserr_fail_str ( err , fail_str ) ;
2008-12-23 16:15:54 +03:00
}
2014-09-03 02:51:03 +04:00
# if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return PIDT2NUM ( pid ) ;
2004-02-16 09:45:32 +03:00
# else
return Qnil ;
2002-08-28 12:05:23 +04:00
# endif
1998-01-16 15:13:05 +03:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* sleep ( [ duration ] ) - > integer
2004-06-29 05:17:39 +04:00
*
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
* Suspends the current thread for _duration_ seconds ( which may be any number ,
* including a + Float + with fractional seconds ) . Returns the actual number of
* seconds slept ( rounded ) , which may be less than that asked for if another
2019-03-28 06:33:35 +03:00
* thread calls Thread # run . Called without an argument , sleep ( )
2009-04-01 08:20:05 +04:00
* will sleep forever .
2004-06-29 05:17:39 +04:00
*
2008-03-09 04:04:46 +03:00
* Time . new # = > 2008 - 03 - 08 19 : 56 : 19 + 0900
2004-01-02 09:01:12 +03:00
* sleep 1.2 # = > 1
2008-03-09 04:04:46 +03:00
* Time . new # = > 2008 - 03 - 08 19 : 56 : 20 + 0900
2004-01-02 09:01:12 +03:00
* sleep 1.9 # = > 2
2008-03-09 04:04:46 +03:00
* Time . new # = > 2008 - 03 - 08 19 : 56 : 22 + 0900
2004-01-02 09:01:12 +03:00
*/
1998-01-16 15:13:05 +03:00
static VALUE
2019-08-28 12:19:11 +03:00
rb_f_sleep ( int argc , VALUE * argv , VALUE _ )
1998-01-16 15:13:05 +03:00
{
2020-06-09 07:30:43 +03:00
time_t beg = time ( 0 ) ;
2021-02-09 09:39:56 +03:00
VALUE scheduler = rb_fiber_scheduler_current ( ) ;
1998-01-16 15:13:05 +03:00
2020-05-14 13:10:55 +03:00
if ( scheduler ! = Qnil ) {
2021-02-09 09:39:56 +03:00
rb_fiber_scheduler_kernel_sleepv ( scheduler , argc , argv ) ;
1998-01-16 15:13:05 +03:00
}
else {
2020-06-09 07:30:43 +03:00
if ( argc = = 0 ) {
rb_thread_sleep_forever ( ) ;
}
else {
rb_check_arity ( argc , 0 , 1 ) ;
rb_thread_wait_for ( rb_time_interval ( argv [ 0 ] ) ) ;
}
1998-01-16 15:13:05 +03:00
}
2020-05-14 13:10:55 +03:00
time_t end = time ( 0 ) - beg ;
1998-01-16 15:13:05 +03:00
2020-06-09 16:25:46 +03:00
return TIMET2NUM ( end ) ;
1998-01-16 15:13:05 +03:00
}
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . getpgrp - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the process group ID for this process . Not available on
* all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . getpgid ( 0 ) # = > 25527
* Process . getpgrp # = > 25527
*/
1998-01-16 15:13:05 +03:00
static VALUE
2019-08-28 11:48:48 +03:00
proc_getpgrp ( VALUE _ )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t pgrp ;
1998-01-16 15:13:05 +03:00
2001-08-06 07:05:23 +04:00
# if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
1998-01-16 15:13:05 +03:00
pgrp = getpgrp ( ) ;
if ( pgrp < 0 ) rb_sys_fail ( 0 ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return PIDT2NUM ( pgrp ) ;
2009-04-16 20:58:06 +04:00
# else /* defined(HAVE_GETPGID) */
2001-08-06 07:05:23 +04:00
pgrp = getpgid ( 0 ) ;
if ( pgrp < 0 ) rb_sys_fail ( 0 ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return PIDT2NUM ( pgrp ) ;
1999-08-13 09:45:20 +04:00
# endif
1998-01-16 15:13:05 +03:00
}
2009-04-16 20:58:06 +04:00
# else
# define proc_getpgrp rb_f_notimplement
# endif
1998-01-16 15:13:05 +03:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . setpgrp - > 0
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Equivalent to < code > setpgid ( 0 , 0 ) < / code > . Not available on all
* platforms .
*/
1998-01-16 15:13:05 +03:00
static VALUE
2019-08-28 11:48:48 +03:00
proc_setpgrp ( VALUE _ )
1998-01-16 15:13:05 +03:00
{
2002-07-11 12:22:18 +04:00
/* check for posix setpgid() first; this matches the posix */
/* getpgrp() above. It appears that configure will set SETPGRP_VOID */
2007-12-31 15:55:50 +03:00
/* even though setpgrp(0,0) would be preferred. The posix call avoids */
2002-07-11 12:22:18 +04:00
/* this confusion. */
# ifdef HAVE_SETPGID
2004-11-18 06:45:23 +03:00
if ( setpgid ( 0 , 0 ) < 0 ) rb_sys_fail ( 0 ) ;
2009-04-18 18:10:06 +04:00
# elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
1998-01-16 15:13:05 +03:00
if ( setpgrp ( ) < 0 ) rb_sys_fail ( 0 ) ;
1999-01-20 07:59:39 +03:00
# endif
2002-03-11 11:02:04 +03:00
return INT2FIX ( 0 ) ;
1999-01-20 07:59:39 +03:00
}
2009-04-16 20:58:06 +04:00
# else
# define proc_setpgrp rb_f_notimplement
# endif
1999-01-20 07:59:39 +03:00
2004-01-02 09:01:12 +03:00
2009-06-22 16:23:06 +04:00
# if defined(HAVE_GETPGID)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . getpgid ( pid ) - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the process group ID for the given process id . Not
* available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . getpgid ( Process . ppid ( ) ) # = > 25527
*/
1999-01-20 07:59:39 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_getpgid ( VALUE obj , VALUE pid )
1999-01-20 07:59:39 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t i ;
1999-01-20 07:59:39 +03:00
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
i = getpgid ( NUM2PIDT ( pid ) ) ;
2002-03-11 11:02:04 +03:00
if ( i < 0 ) rb_sys_fail ( 0 ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return PIDT2NUM ( i ) ;
2009-04-16 20:58:06 +04:00
}
1999-01-20 07:59:39 +03:00
# else
2009-04-16 20:58:06 +04:00
# define proc_getpgid rb_f_notimplement
1999-01-20 07:59:39 +03:00
# endif
1998-01-16 15:13:05 +03:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# ifdef HAVE_SETPGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . setpgid ( pid , integer ) - > 0
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Sets the process group ID of _pid_ ( 0 indicates this
* process ) to < em > integer < / em > . Not available on all platforms .
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_setpgid ( VALUE obj , VALUE pid , VALUE pgrp )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t ipid , ipgrp ;
1998-01-16 15:13:05 +03:00
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
ipid = NUM2PIDT ( pid ) ;
ipgrp = NUM2PIDT ( pgrp ) ;
1998-01-16 15:13:05 +03:00
if ( setpgid ( ipid , ipgrp ) < 0 ) rb_sys_fail ( 0 ) ;
2000-03-13 10:18:45 +03:00
return INT2FIX ( 0 ) ;
2009-04-16 20:58:06 +04:00
}
1999-01-20 07:59:39 +03:00
# else
2009-04-16 20:58:06 +04:00
# define proc_setpgid rb_f_notimplement
1999-01-20 07:59:39 +03:00
# endif
2004-01-02 09:01:12 +03:00
2012-11-24 06:51:24 +04:00
# ifdef HAVE_GETSID
/*
* call - seq :
* Process . getsid ( ) - > integer
* Process . getsid ( pid ) - > integer
*
2015-11-04 05:38:25 +03:00
* Returns the session ID for the given process id . If not given ,
2012-11-24 06:51:24 +04:00
* return current process sid . Not available on all platforms .
*
* Process . getsid ( ) # = > 27422
* Process . getsid ( 0 ) # = > 27422
* Process . getsid ( Process . pid ( ) ) # = > 27422
*/
static VALUE
2019-08-28 11:48:48 +03:00
proc_getsid ( int argc , VALUE * argv , VALUE _ )
2012-11-24 06:51:24 +04:00
{
rb_pid_t sid ;
2016-04-14 07:41:47 +03:00
rb_pid_t pid = 0 ;
2012-11-24 06:51:24 +04:00
2016-04-14 07:41:47 +03:00
if ( rb_check_arity ( argc , 0 , 1 ) = = 1 & & ! NIL_P ( argv [ 0 ] ) )
pid = NUM2PIDT ( argv [ 0 ] ) ;
2012-11-24 06:51:24 +04:00
2016-04-14 07:41:47 +03:00
sid = getsid ( pid ) ;
2012-11-24 06:51:24 +04:00
if ( sid < 0 ) rb_sys_fail ( 0 ) ;
return PIDT2NUM ( sid ) ;
}
# else
# define proc_getsid rb_f_notimplement
# endif
2009-04-16 20:58:06 +04:00
# if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
2010-04-02 03:25:10 +04:00
# if !defined(HAVE_SETSID)
static rb_pid_t ruby_setsid ( void ) ;
# define setsid() ruby_setsid()
# endif
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . setsid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Establishes this process as a new session and process group
* leader , with no controlling tty . Returns the session id . Not
* available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . setsid # = > 27422
*/
1999-01-20 07:59:39 +03:00
static VALUE
2019-08-28 11:48:48 +03:00
proc_setsid ( VALUE _ )
1999-01-20 07:59:39 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t pid ;
1999-01-20 07:59:39 +03:00
1999-12-14 09:50:43 +03:00
pid = setsid ( ) ;
1999-01-20 07:59:39 +03:00
if ( pid < 0 ) rb_sys_fail ( 0 ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return PIDT2NUM ( pid ) ;
2010-04-02 03:25:10 +04:00
}
# if !defined(HAVE_SETSID)
# define HAVE_SETSID 1
static rb_pid_t
ruby_setsid ( void )
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_pid_t pid ;
int ret ;
2000-06-13 13:42:40 +04:00
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
pid = getpid ( ) ;
2000-06-13 13:42:40 +04:00
# if defined(SETPGRP_VOID)
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
ret = setpgrp ( ) ;
/* If `pid_t setpgrp(void)' is equivalent to setsid(),
` ret ' will be the same value as ` pid ' , and following open ( ) will fail .
In Linux , ` int setpgrp ( void ) ' is equivalent to setpgid ( 0 , 0 ) . */
2000-06-13 13:42:40 +04:00
# else
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
ret = setpgrp ( 0 , pid ) ;
2000-06-13 13:42:40 +04:00
# endif
2010-04-02 03:25:10 +04:00
if ( ret = = - 1 ) return - 1 ;
2000-06-13 13:42:40 +04:00
2011-10-29 08:01:54 +04:00
if ( ( fd = rb_cloexec_open ( " /dev/tty " , O_RDWR , 0 ) ) > = 0 ) {
rb_update_max_fd ( fd ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
ioctl ( fd , TIOCNOTTY , NULL ) ;
close ( fd ) ;
}
2010-04-02 03:25:10 +04:00
return pid ;
1999-01-20 07:59:39 +03:00
}
2010-04-02 03:25:10 +04:00
# endif
2009-04-16 20:58:06 +04:00
# else
# define proc_setsid rb_f_notimplement
# endif
1998-01-16 15:13:05 +03:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# ifdef HAVE_GETPRIORITY
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . getpriority ( kind , integer ) - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Gets the scheduling priority for specified process , process group ,
* or user . < em > kind < / em > indicates the kind of entity to find : one
2019-03-28 06:33:35 +03:00
* of Process : : PRIO_PGRP ,
* Process : : PRIO_USER , or
* Process : : PRIO_PROCESS . _integer_ is an id
2004-01-02 09:01:12 +03:00
* indicating the particular process , process group , or user ( an id
* of 0 means _current_ ) . Lower priorities are more favorable
* for scheduling . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . getpriority ( Process : : PRIO_USER , 0 ) # = > 19
* Process . getpriority ( Process : : PRIO_PROCESS , 0 ) # = > 19
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_getpriority ( VALUE obj , VALUE which , VALUE who )
1998-01-16 15:13:05 +03:00
{
int prio , iwhich , iwho ;
iwhich = NUM2INT ( which ) ;
iwho = NUM2INT ( who ) ;
2000-07-21 12:45:34 +04:00
errno = 0 ;
1998-01-16 15:13:05 +03:00
prio = getpriority ( iwhich , iwho ) ;
2000-07-21 12:45:34 +04:00
if ( errno ) rb_sys_fail ( 0 ) ;
1998-01-16 15:13:05 +03:00
return INT2FIX ( prio ) ;
2009-04-16 20:58:06 +04:00
}
1998-01-16 15:13:05 +03:00
# else
2009-04-16 20:58:06 +04:00
# define proc_getpriority rb_f_notimplement
1998-01-16 15:13:05 +03:00
# endif
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# ifdef HAVE_GETPRIORITY
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . setpriority ( kind , integer , priority ) - > 0
2004-06-29 05:17:39 +04:00
*
2019-10-24 19:35:36 +03:00
* See Process . getpriority .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . setpriority ( Process : : PRIO_USER , 0 , 19 ) # = > 0
* Process . setpriority ( Process : : PRIO_PROCESS , 0 , 19 ) # = > 0
* Process . getpriority ( Process : : PRIO_USER , 0 ) # = > 19
* Process . getpriority ( Process : : PRIO_PROCESS , 0 ) # = > 19
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_setpriority ( VALUE obj , VALUE which , VALUE who , VALUE prio )
1998-01-16 15:13:05 +03:00
{
int iwhich , iwho , iprio ;
iwhich = NUM2INT ( which ) ;
iwho = NUM2INT ( who ) ;
iprio = NUM2INT ( prio ) ;
if ( setpriority ( iwhich , iwho , iprio ) < 0 )
rb_sys_fail ( 0 ) ;
return INT2FIX ( 0 ) ;
2009-04-16 20:58:06 +04:00
}
1998-01-16 15:13:05 +03:00
# else
2009-04-16 20:58:06 +04:00
# define proc_setpriority rb_f_notimplement
1998-01-16 15:13:05 +03:00
# endif
2011-03-07 11:44:45 +03:00
# if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
2008-02-22 19:12:32 +03:00
static int
2017-07-14 07:43:16 +03:00
rlimit_resource_name2int ( const char * name , long len , int casetype )
2008-02-22 19:12:32 +03:00
{
2010-09-11 23:28:07 +04:00
int resource ;
const char * p ;
# define RESCHECK(r) \
do { \
2017-07-14 07:43:16 +03:00
if ( len = = rb_strlen_lit ( # r ) & & STRCASECMP ( name , # r ) = = 0 ) { \
2010-09-11 23:28:07 +04:00
resource = RLIMIT_ # # r ; \
goto found ; \
} \
} while ( 0 )
switch ( TOUPPER ( * name ) ) {
2008-02-22 19:12:32 +03:00
case ' A ' :
# ifdef RLIMIT_AS
2010-09-11 23:28:07 +04:00
RESCHECK ( AS ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' C ' :
# ifdef RLIMIT_CORE
2010-09-11 23:28:07 +04:00
RESCHECK ( CORE ) ;
2008-02-22 19:12:32 +03:00
# endif
# ifdef RLIMIT_CPU
2010-09-11 23:28:07 +04:00
RESCHECK ( CPU ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' D ' :
# ifdef RLIMIT_DATA
2010-09-11 23:28:07 +04:00
RESCHECK ( DATA ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' F ' :
# ifdef RLIMIT_FSIZE
2010-09-11 23:28:07 +04:00
RESCHECK ( FSIZE ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' M ' :
# ifdef RLIMIT_MEMLOCK
2010-09-11 23:28:07 +04:00
RESCHECK ( MEMLOCK ) ;
2010-09-12 03:38:44 +04:00
# endif
# ifdef RLIMIT_MSGQUEUE
RESCHECK ( MSGQUEUE ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' N ' :
# ifdef RLIMIT_NOFILE
2010-09-11 23:28:07 +04:00
RESCHECK ( NOFILE ) ;
2008-02-22 19:12:32 +03:00
# endif
# ifdef RLIMIT_NPROC
2010-09-11 23:28:07 +04:00
RESCHECK ( NPROC ) ;
2010-09-12 03:38:44 +04:00
# endif
# ifdef RLIMIT_NICE
RESCHECK ( NICE ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' R ' :
# ifdef RLIMIT_RSS
2010-09-11 23:28:07 +04:00
RESCHECK ( RSS ) ;
2010-09-12 03:38:44 +04:00
# endif
# ifdef RLIMIT_RTPRIO
RESCHECK ( RTPRIO ) ;
# endif
# ifdef RLIMIT_RTTIME
RESCHECK ( RTTIME ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
case ' S ' :
# ifdef RLIMIT_STACK
2010-09-11 23:28:07 +04:00
RESCHECK ( STACK ) ;
2008-02-22 19:12:32 +03:00
# endif
# ifdef RLIMIT_SBSIZE
2010-09-11 23:28:07 +04:00
RESCHECK ( SBSIZE ) ;
2010-09-12 03:38:44 +04:00
# endif
# ifdef RLIMIT_SIGPENDING
RESCHECK ( SIGPENDING ) ;
2008-02-22 19:12:32 +03:00
# endif
break ;
}
2008-04-24 18:46:39 +04:00
return - 1 ;
2010-09-11 23:28:07 +04:00
found :
switch ( casetype ) {
case 0 :
for ( p = name ; * p ; p + + )
if ( ! ISUPPER ( * p ) )
return - 1 ;
break ;
case 1 :
for ( p = name ; * p ; p + + )
if ( ! ISLOWER ( * p ) )
return - 1 ;
break ;
default :
rb_bug ( " unexpected casetype " ) ;
}
return resource ;
# undef RESCHECK
2008-04-24 18:46:39 +04:00
}
static int
2017-07-14 07:43:16 +03:00
rlimit_type_by_hname ( const char * name , long len )
2008-04-24 18:46:39 +04:00
{
2017-07-14 07:43:16 +03:00
return rlimit_resource_name2int ( name , len , 0 ) ;
2008-04-24 18:46:39 +04:00
}
static int
2017-07-14 07:43:16 +03:00
rlimit_type_by_lname ( const char * name , long len )
2008-04-24 18:46:39 +04:00
{
2017-07-14 07:43:16 +03:00
return rlimit_resource_name2int ( name , len , 1 ) ;
2008-04-24 18:46:39 +04:00
}
2017-07-13 23:47:36 +03:00
static int
rlimit_type_by_sym ( VALUE key )
{
2017-07-14 07:43:16 +03:00
VALUE name = rb_sym2str ( key ) ;
const char * rname = RSTRING_PTR ( name ) ;
long len = RSTRING_LEN ( name ) ;
2017-07-13 23:47:36 +03:00
int rtype = - 1 ;
2017-07-14 07:43:16 +03:00
static const char prefix [ ] = " rlimit_ " ;
enum { prefix_len = sizeof ( prefix ) - 1 } ;
2017-07-13 23:47:36 +03:00
2017-07-14 07:43:16 +03:00
if ( len > prefix_len & & strncmp ( prefix , rname , prefix_len ) = = 0 ) {
rtype = rlimit_type_by_lname ( rname + prefix_len , len - prefix_len ) ;
2017-07-13 23:47:36 +03:00
}
RB_GC_GUARD ( key ) ;
return rtype ;
}
2008-04-24 18:46:39 +04:00
static int
rlimit_resource_type ( VALUE rtype )
{
const char * name ;
2017-07-14 07:43:16 +03:00
long len ;
2008-04-24 18:46:39 +04:00
VALUE v ;
int r ;
switch ( TYPE ( rtype ) ) {
case T_SYMBOL :
2014-07-30 17:46:41 +04:00
v = rb_sym2str ( rtype ) ;
name = RSTRING_PTR ( v ) ;
2017-07-14 07:43:16 +03:00
len = RSTRING_LEN ( v ) ;
2008-04-24 18:46:39 +04:00
break ;
default :
v = rb_check_string_type ( rtype ) ;
if ( ! NIL_P ( v ) ) {
rtype = v ;
case T_STRING :
name = StringValueCStr ( rtype ) ;
2017-07-14 07:43:16 +03:00
len = RSTRING_LEN ( rtype ) ;
2008-04-24 18:46:39 +04:00
break ;
}
/* fall through */
case T_FIXNUM :
case T_BIGNUM :
return NUM2INT ( rtype ) ;
}
2017-07-14 07:43:16 +03:00
r = rlimit_type_by_hname ( name , len ) ;
2008-04-24 18:46:39 +04:00
if ( r ! = - 1 )
return r ;
2017-07-14 07:43:16 +03:00
rb_raise ( rb_eArgError , " invalid resource name: % " PRIsVALUE , rtype ) ;
2012-04-14 03:45:37 +04:00
2018-07-24 08:38:07 +03:00
UNREACHABLE_RETURN ( - 1 ) ;
2008-02-22 19:12:32 +03:00
}
static rlim_t
rlimit_resource_value ( VALUE rval )
{
const char * name ;
VALUE v ;
switch ( TYPE ( rval ) ) {
case T_SYMBOL :
2014-07-30 17:46:41 +04:00
v = rb_sym2str ( rval ) ;
name = RSTRING_PTR ( v ) ;
2008-02-22 19:12:32 +03:00
break ;
default :
v = rb_check_string_type ( rval ) ;
if ( ! NIL_P ( v ) ) {
rval = v ;
case T_STRING :
name = StringValueCStr ( rval ) ;
break ;
}
/* fall through */
case T_FIXNUM :
case T_BIGNUM :
2008-03-22 20:53:07 +03:00
return NUM2RLIM ( rval ) ;
2008-02-22 19:12:32 +03:00
}
# ifdef RLIM_INFINITY
if ( strcmp ( name , " INFINITY " ) = = 0 ) return RLIM_INFINITY ;
# endif
# ifdef RLIM_SAVED_MAX
if ( strcmp ( name , " SAVED_MAX " ) = = 0 ) return RLIM_SAVED_MAX ;
# endif
# ifdef RLIM_SAVED_CUR
if ( strcmp ( name , " SAVED_CUR " ) = = 0 ) return RLIM_SAVED_CUR ;
# endif
2014-03-31 01:00:53 +04:00
rb_raise ( rb_eArgError , " invalid resource value: % " PRIsVALUE , rval ) ;
2012-04-14 03:45:37 +04:00
2018-07-24 08:38:07 +03:00
UNREACHABLE_RETURN ( ( rlim_t ) - 1 ) ;
2008-02-22 19:12:32 +03:00
}
# endif
2009-04-16 20:58:06 +04:00
# if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
2004-11-14 13:06:16 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . getrlimit ( resource ) - > [ cur_limit , max_limit ]
2004-11-14 13:06:16 +03:00
*
* Gets the resource limit of the process .
* _cur_limit_ means current ( soft ) limit and
* _max_limit_ means maximum ( hard ) limit .
*
2008-02-22 19:12:32 +03:00
* _resource_ indicates the kind of resource to limit .
* It is specified as a symbol such as < code > : CORE < / code > ,
* a string such as < code > " CORE " < / code > or
2019-03-28 06:33:35 +03:00
* a constant such as Process : : RLIMIT_CORE .
2004-11-14 13:06:16 +03:00
* See Process . setrlimit for details .
*
2019-03-28 06:33:35 +03:00
* _cur_limit_ and _max_limit_ may be Process : : RLIM_INFINITY ,
* Process : : RLIM_SAVED_MAX or
* Process : : RLIM_SAVED_CUR .
2004-11-14 13:06:16 +03:00
* See Process . setrlimit and the system getrlimit ( 2 ) manual for details .
*/
static VALUE
proc_getrlimit ( VALUE obj , VALUE resource )
{
struct rlimit rlim ;
2008-02-22 19:12:32 +03:00
if ( getrlimit ( rlimit_resource_type ( resource ) , & rlim ) < 0 ) {
2004-12-23 17:43:30 +03:00
rb_sys_fail ( " getrlimit " ) ;
2004-11-14 13:06:16 +03:00
}
return rb_assoc_new ( RLIM2NUM ( rlim . rlim_cur ) , RLIM2NUM ( rlim . rlim_max ) ) ;
2009-04-16 20:58:06 +04:00
}
2004-11-14 13:06:16 +03:00
# else
2009-04-16 20:58:06 +04:00
# define proc_getrlimit rb_f_notimplement
2004-11-14 13:06:16 +03:00
# endif
2009-04-16 20:58:06 +04:00
# if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
2004-11-14 13:06:16 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . setrlimit ( resource , cur_limit , max_limit ) - > nil
* Process . setrlimit ( resource , cur_limit ) - > nil
2004-11-14 13:06:16 +03:00
*
* Sets the resource limit of the process .
* _cur_limit_ means current ( soft ) limit and
* _max_limit_ means maximum ( hard ) limit .
*
2005-09-24 20:36:11 +04:00
* If _max_limit_ is not given , _cur_limit_ is used .
2004-11-14 13:06:16 +03:00
*
2005-09-24 20:36:11 +04:00
* _resource_ indicates the kind of resource to limit .
2008-02-22 19:12:32 +03:00
* It should be a symbol such as < code > : CORE < / code > ,
* a string such as < code > " CORE " < / code > or
2019-03-28 06:33:35 +03:00
* a constant such as Process : : RLIMIT_CORE .
2008-02-22 19:12:32 +03:00
* The available resources are OS dependent .
2005-09-24 20:36:11 +04:00
* Ruby may support following resources .
*
2010-09-12 03:38:44 +04:00
* [ AS ] total available memory ( bytes ) ( SUSv3 , NetBSD , FreeBSD , OpenBSD but 4.4 BSD - Lite )
2008-02-22 19:12:32 +03:00
* [ CORE ] core size ( bytes ) ( SUSv3 )
* [ CPU ] CPU time ( seconds ) ( SUSv3 )
* [ DATA ] data segment ( bytes ) ( SUSv3 )
* [ FSIZE ] file size ( bytes ) ( SUSv3 )
* [ MEMLOCK ] total size for mlock ( 2 ) ( bytes ) ( 4.4 BSD , GNU / Linux )
2010-09-12 03:38:44 +04:00
* [ MSGQUEUE ] allocation for POSIX message queues ( bytes ) ( GNU / Linux )
* [ NICE ] ceiling on process ' s nice ( 2 ) value ( number ) ( GNU / Linux )
* [ NOFILE ] file descriptors ( number ) ( SUSv3 )
2008-02-22 19:12:32 +03:00
* [ NPROC ] number of processes for the user ( number ) ( 4.4 BSD , GNU / Linux )
* [ RSS ] resident memory size ( bytes ) ( 4.2 BSD , GNU / Linux )
2010-09-12 03:38:44 +04:00
* [ RTPRIO ] ceiling on the process ' s real - time priority ( number ) ( GNU / Linux )
* [ RTTIME ] CPU time for real - time process ( us ) ( GNU / Linux )
2008-02-22 19:12:32 +03:00
* [ SBSIZE ] all socket buffers ( bytes ) ( NetBSD , FreeBSD )
2010-09-12 03:38:44 +04:00
* [ SIGPENDING ] number of queued signals allowed ( signals ) ( GNU / Linux )
* [ STACK ] stack size ( bytes ) ( SUSv3 )
2008-02-22 19:12:32 +03:00
*
* _cur_limit_ and _max_limit_ may be
* < code > : INFINITY < / code > , < code > " INFINITY " < / code > or
2019-03-28 06:33:35 +03:00
* Process : : RLIM_INFINITY ,
2004-11-14 13:06:16 +03:00
* which means that the resource is not limited .
2019-03-28 06:33:35 +03:00
* They may be Process : : RLIM_SAVED_MAX ,
* Process : : RLIM_SAVED_CUR and
2008-02-22 19:12:32 +03:00
* corresponding symbols and strings too .
2004-11-14 13:06:16 +03:00
* See system setrlimit ( 2 ) manual for details .
*
2010-09-12 03:38:44 +04:00
* The following example raises the soft limit of core size to
2008-02-22 19:12:32 +03:00
* the hard limit to try to make core dump possible .
*
* Process . setrlimit ( : CORE , Process . getrlimit ( : CORE ) [ 1 ] )
*
2004-11-14 13:06:16 +03:00
*/
static VALUE
2005-09-24 20:36:11 +04:00
proc_setrlimit ( int argc , VALUE * argv , VALUE obj )
2004-11-14 13:06:16 +03:00
{
2005-09-24 20:36:11 +04:00
VALUE resource , rlim_cur , rlim_max ;
2004-11-14 13:06:16 +03:00
struct rlimit rlim ;
2016-04-14 07:41:47 +03:00
rb_check_arity ( argc , 2 , 3 ) ;
resource = argv [ 0 ] ;
rlim_cur = argv [ 1 ] ;
if ( argc < 3 | | NIL_P ( rlim_max = argv [ 2 ] ) )
2005-09-24 20:36:11 +04:00
rlim_max = rlim_cur ;
2008-02-22 19:12:32 +03:00
rlim . rlim_cur = rlimit_resource_value ( rlim_cur ) ;
rlim . rlim_max = rlimit_resource_value ( rlim_max ) ;
2004-11-14 13:06:16 +03:00
2008-02-22 19:12:32 +03:00
if ( setrlimit ( rlimit_resource_type ( resource ) , & rlim ) < 0 ) {
2004-12-23 17:43:30 +03:00
rb_sys_fail ( " setrlimit " ) ;
2004-11-14 13:06:16 +03:00
}
return Qnil ;
2009-04-16 20:58:06 +04:00
}
2004-11-14 13:06:16 +03:00
# else
2009-04-16 20:58:06 +04:00
# define proc_setrlimit rb_f_notimplement
2004-11-14 13:06:16 +03:00
# endif
2003-08-29 12:34:14 +04:00
static int under_uid_switch = 0 ;
2003-11-04 12:13:57 +03:00
static void
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
check_uid_switch ( void )
2003-11-04 12:13:57 +03:00
{
if ( under_uid_switch ) {
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
rb_raise ( rb_eRuntimeError , " can't handle UID while evaluating block given to Process::UID.switch method " ) ;
2003-11-04 12:13:57 +03:00
}
}
2003-08-29 12:34:14 +04:00
static int under_gid_switch = 0 ;
2003-11-04 12:13:57 +03:00
static void
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
check_gid_switch ( void )
2003-11-04 12:13:57 +03:00
{
if ( under_gid_switch ) {
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
rb_raise ( rb_eRuntimeError , " can't handle GID while evaluating block given to Process::UID.switch method " ) ;
2003-11-04 12:13:57 +03:00
}
}
2003-08-29 12:34:14 +04:00
2004-01-02 09:01:12 +03:00
2020-04-15 14:29:16 +03:00
# if defined(HAVE_PWD_H)
/**
* Best - effort attempt to obtain the name of the login user , if any ,
* associated with the process . Processes not descended from login ( 1 ) ( or
* similar ) may not have a logged - in user ; returns Qnil in that case .
*/
VALUE
rb_getlogin ( void )
{
# if ( !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) )
return Qnil ;
# else
char MAYBE_UNUSED ( * login ) = NULL ;
# ifdef USE_GETLOGIN_R
2020-08-22 03:33:45 +03:00
# if defined(__FreeBSD__)
typedef int getlogin_r_size_t ;
# else
typedef size_t getlogin_r_size_t ;
# endif
2020-04-15 14:29:16 +03:00
long loginsize = GETLOGIN_R_SIZE_INIT ; /* maybe -1 */
if ( loginsize < 0 )
loginsize = GETLOGIN_R_SIZE_DEFAULT ;
VALUE maybe_result = rb_str_buf_new ( loginsize ) ;
login = RSTRING_PTR ( maybe_result ) ;
loginsize = rb_str_capacity ( maybe_result ) ;
rb_str_set_len ( maybe_result , loginsize ) ;
int gle ;
errno = 0 ;
2020-08-22 03:33:45 +03:00
while ( ( gle = getlogin_r ( login , ( getlogin_r_size_t ) loginsize ) ) ! = 0 ) {
2020-04-15 14:29:16 +03:00
if ( gle = = ENOTTY | | gle = = ENXIO | | gle = = ENOENT ) {
rb_str_resize ( maybe_result , 0 ) ;
return Qnil ;
}
if ( gle ! = ERANGE | | loginsize > = GETLOGIN_R_SIZE_LIMIT ) {
rb_str_resize ( maybe_result , 0 ) ;
rb_syserr_fail ( gle , " getlogin_r " ) ;
}
rb_str_modify_expand ( maybe_result , loginsize ) ;
login = RSTRING_PTR ( maybe_result ) ;
loginsize = rb_str_capacity ( maybe_result ) ;
}
if ( login = = NULL ) {
rb_str_resize ( maybe_result , 0 ) ;
return Qnil ;
}
return maybe_result ;
# elif USE_GETLOGIN
errno = 0 ;
login = getlogin ( ) ;
if ( errno ) {
if ( errno = = ENOTTY | | errno = = ENXIO | | errno = = ENOENT ) {
return Qnil ;
}
rb_syserr_fail ( errno , " getlogin " ) ;
}
return login ? rb_str_new_cstr ( login ) : Qnil ;
# endif
# endif
}
VALUE
rb_getpwdirnam_for_login ( VALUE login_name )
{
# if ( !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM) )
return Qnil ;
# else
if ( NIL_P ( login_name ) ) {
/* nothing to do; no name with which to query the password database */
return Qnil ;
}
char * login = RSTRING_PTR ( login_name ) ;
struct passwd * pwptr ;
# ifdef USE_GETPWNAM_R
struct passwd pwdnm ;
char * bufnm ;
long bufsizenm = GETPW_R_SIZE_INIT ; /* maybe -1 */
if ( bufsizenm < 0 )
bufsizenm = GETPW_R_SIZE_DEFAULT ;
VALUE getpwnm_tmp = rb_str_tmp_new ( bufsizenm ) ;
bufnm = RSTRING_PTR ( getpwnm_tmp ) ;
bufsizenm = rb_str_capacity ( getpwnm_tmp ) ;
rb_str_set_len ( getpwnm_tmp , bufsizenm ) ;
int enm ;
errno = 0 ;
while ( ( enm = getpwnam_r ( login , & pwdnm , bufnm , bufsizenm , & pwptr ) ) ! = 0 ) {
if ( enm = = ENOENT | | enm = = ESRCH | | enm = = EBADF | | enm = = EPERM ) {
/* not found; non-errors */
rb_str_resize ( getpwnm_tmp , 0 ) ;
return Qnil ;
}
if ( enm ! = ERANGE | | bufsizenm > = GETPW_R_SIZE_LIMIT ) {
rb_str_resize ( getpwnm_tmp , 0 ) ;
rb_syserr_fail ( enm , " getpwnam_r " ) ;
}
rb_str_modify_expand ( getpwnm_tmp , bufsizenm ) ;
bufnm = RSTRING_PTR ( getpwnm_tmp ) ;
bufsizenm = rb_str_capacity ( getpwnm_tmp ) ;
}
if ( pwptr = = NULL ) {
/* no record in the password database for the login name */
rb_str_resize ( getpwnm_tmp , 0 ) ;
return Qnil ;
}
/* found it */
VALUE result = rb_str_new_cstr ( pwptr - > pw_dir ) ;
rb_str_resize ( getpwnm_tmp , 0 ) ;
return result ;
# elif USE_GETPWNAM
errno = 0 ;
pwptr = getpwnam ( login ) ;
if ( pwptr ) {
/* found it */
return rb_str_new_cstr ( pwptr - > pw_dir ) ;
}
if ( errno
/* avoid treating as errors errno values that indicate "not found" */
& & ( errno ! = ENOENT & & errno ! = ESRCH & & errno ! = EBADF & & errno ! = EPERM ) ) {
rb_syserr_fail ( errno , " getpwnam " ) ;
}
return Qnil ; /* not found */
# endif
# endif
}
/**
* Look up the user ' s dflt home dir in the password db , by uid .
*/
VALUE
rb_getpwdiruid ( void )
{
# if !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID)
/* Should never happen... </famous-last-words> */
return Qnil ;
# else
uid_t ruid = getuid ( ) ;
struct passwd * pwptr ;
# ifdef USE_GETPWUID_R
struct passwd pwdid ;
char * bufid ;
long bufsizeid = GETPW_R_SIZE_INIT ; /* maybe -1 */
if ( bufsizeid < 0 )
bufsizeid = GETPW_R_SIZE_DEFAULT ;
VALUE getpwid_tmp = rb_str_tmp_new ( bufsizeid ) ;
bufid = RSTRING_PTR ( getpwid_tmp ) ;
bufsizeid = rb_str_capacity ( getpwid_tmp ) ;
rb_str_set_len ( getpwid_tmp , bufsizeid ) ;
int eid ;
errno = 0 ;
while ( ( eid = getpwuid_r ( ruid , & pwdid , bufid , bufsizeid , & pwptr ) ) ! = 0 ) {
if ( eid = = ENOENT | | eid = = ESRCH | | eid = = EBADF | | eid = = EPERM ) {
/* not found; non-errors */
rb_str_resize ( getpwid_tmp , 0 ) ;
return Qnil ;
}
if ( eid ! = ERANGE | | bufsizeid > = GETPW_R_SIZE_LIMIT ) {
rb_str_resize ( getpwid_tmp , 0 ) ;
rb_syserr_fail ( eid , " getpwuid_r " ) ;
}
rb_str_modify_expand ( getpwid_tmp , bufsizeid ) ;
bufid = RSTRING_PTR ( getpwid_tmp ) ;
bufsizeid = rb_str_capacity ( getpwid_tmp ) ;
}
if ( pwptr = = NULL ) {
/* no record in the password database for the uid */
rb_str_resize ( getpwid_tmp , 0 ) ;
return Qnil ;
}
/* found it */
VALUE result = rb_str_new_cstr ( pwptr - > pw_dir ) ;
rb_str_resize ( getpwid_tmp , 0 ) ;
return result ;
# elif defined(USE_GETPWUID)
errno = 0 ;
pwptr = getpwuid ( ruid ) ;
if ( pwptr ) {
/* found it */
return rb_str_new_cstr ( pwptr - > pw_dir ) ;
}
if ( errno
/* avoid treating as errors errno values that indicate "not found" */
& & ( errno = = ENOENT | | errno = = ESRCH | | errno = = EBADF | | errno = = EPERM ) ) {
rb_syserr_fail ( errno , " getpwuid " ) ;
}
return Qnil ; /* not found */
# endif
# endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */
}
# endif /* HAVE_PWD_H */
2004-01-02 09:01:12 +03:00
/*********************************************************************
* Document - class : Process : : Sys
*
2019-03-28 06:33:35 +03:00
* The Process : : Sys module contains UID and GID
2004-01-02 09:01:12 +03:00
* functions which provide direct bindings to the system calls of the
* same names instead of the more - portable versions of the same
2019-03-28 06:33:35 +03:00
* functionality found in the Process ,
* Process : : UID , and Process : : GID modules .
2004-01-02 09:01:12 +03:00
*/
2012-03-28 11:40:02 +04:00
# if defined(HAVE_PWD_H)
static rb_uid_t
obj2uid ( VALUE id
2013-02-07 19:07:35 +04:00
# ifdef USE_GETPWNAM_R
2014-03-08 07:55:01 +04:00
, VALUE * getpw_tmp
2012-03-28 11:40:02 +04:00
# endif
)
{
rb_uid_t uid ;
VALUE tmp ;
if ( FIXNUM_P ( id ) | | NIL_P ( tmp = rb_check_string_type ( id ) ) ) {
uid = NUM2UIDT ( id ) ;
}
else {
const char * usrname = StringValueCStr ( id ) ;
struct passwd * pwptr ;
2013-02-07 19:07:35 +04:00
# ifdef USE_GETPWNAM_R
2012-03-28 11:40:02 +04:00
struct passwd pwbuf ;
2014-03-08 07:55:01 +04:00
char * getpw_buf ;
long getpw_buf_len ;
2017-05-11 05:38:09 +03:00
int e ;
2014-03-08 07:55:01 +04:00
if ( ! * getpw_tmp ) {
2014-03-08 08:08:46 +04:00
getpw_buf_len = GETPW_R_SIZE_INIT ;
if ( getpw_buf_len < 0 ) getpw_buf_len = GETPW_R_SIZE_DEFAULT ;
2017-05-11 02:18:07 +03:00
* getpw_tmp = rb_str_tmp_new ( getpw_buf_len ) ;
2014-03-08 07:55:01 +04:00
}
2017-05-11 02:18:07 +03:00
getpw_buf = RSTRING_PTR ( * getpw_tmp ) ;
getpw_buf_len = rb_str_capacity ( * getpw_tmp ) ;
rb_str_set_len ( * getpw_tmp , getpw_buf_len ) ;
2017-05-11 05:38:09 +03:00
errno = 0 ;
while ( ( e = getpwnam_r ( usrname , & pwbuf , getpw_buf , getpw_buf_len , & pwptr ) ) ! = 0 ) {
if ( e ! = ERANGE | | getpw_buf_len > = GETPW_R_SIZE_LIMIT ) {
2017-05-11 02:18:07 +03:00
rb_str_resize ( * getpw_tmp , 0 ) ;
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( e , " getpwnam_r " ) ;
2014-03-08 08:30:56 +04:00
}
rb_str_modify_expand ( * getpw_tmp , getpw_buf_len ) ;
getpw_buf = RSTRING_PTR ( * getpw_tmp ) ;
getpw_buf_len = rb_str_capacity ( * getpw_tmp ) ;
}
2012-03-28 11:40:02 +04:00
# else
pwptr = getpwnam ( usrname ) ;
# endif
if ( ! pwptr ) {
2013-02-07 19:07:35 +04:00
# ifndef USE_GETPWNAM_R
2012-03-28 11:40:02 +04:00
endpwent ( ) ;
# endif
2020-04-16 14:40:53 +03:00
rb_raise ( rb_eArgError , " can't find user for % " PRIsVALUE , id ) ;
2012-03-28 11:40:02 +04:00
}
uid = pwptr - > pw_uid ;
2013-02-07 19:07:35 +04:00
# ifndef USE_GETPWNAM_R
2012-03-28 11:40:02 +04:00
endpwent ( ) ;
# endif
}
return uid ;
}
# ifdef p_uid_from_name
2013-06-02 07:12:04 +04:00
/*
* call - seq :
* Process : : UID . from_name ( name ) - > uid
*
* Get the user ID by the _name_ .
* If the user is not found , + ArgumentError + will be raised .
*
* Process : : UID . from_name ( " root " ) # = > 0
* Process : : UID . from_name ( " nosuchuser " ) # = > can ' t find user for nosuchuser ( ArgumentError )
*/
2012-03-28 11:40:02 +04:00
static VALUE
p_uid_from_name ( VALUE self , VALUE id )
{
return UIDT2NUM ( OBJ2UID ( id ) ) ;
}
# endif
# endif
# if defined(HAVE_GRP_H)
static rb_gid_t
obj2gid ( VALUE id
2013-02-07 19:07:35 +04:00
# ifdef USE_GETGRNAM_R
2014-03-08 07:55:01 +04:00
, VALUE * getgr_tmp
2012-03-28 11:40:02 +04:00
# endif
)
{
rb_gid_t gid ;
VALUE tmp ;
if ( FIXNUM_P ( id ) | | NIL_P ( tmp = rb_check_string_type ( id ) ) ) {
gid = NUM2GIDT ( id ) ;
}
else {
const char * grpname = StringValueCStr ( id ) ;
struct group * grptr ;
2013-02-07 19:07:35 +04:00
# ifdef USE_GETGRNAM_R
2012-03-28 11:40:02 +04:00
struct group grbuf ;
2014-03-08 07:55:01 +04:00
char * getgr_buf ;
long getgr_buf_len ;
2017-05-11 05:38:09 +03:00
int e ;
2014-03-08 07:55:01 +04:00
if ( ! * getgr_tmp ) {
2014-03-08 08:08:46 +04:00
getgr_buf_len = GETGR_R_SIZE_INIT ;
if ( getgr_buf_len < 0 ) getgr_buf_len = GETGR_R_SIZE_DEFAULT ;
2017-05-11 02:18:07 +03:00
* getgr_tmp = rb_str_tmp_new ( getgr_buf_len ) ;
2014-03-08 07:55:01 +04:00
}
2017-05-11 02:18:07 +03:00
getgr_buf = RSTRING_PTR ( * getgr_tmp ) ;
getgr_buf_len = rb_str_capacity ( * getgr_tmp ) ;
rb_str_set_len ( * getgr_tmp , getgr_buf_len ) ;
2017-05-11 05:38:09 +03:00
errno = 0 ;
while ( ( e = getgrnam_r ( grpname , & grbuf , getgr_buf , getgr_buf_len , & grptr ) ) ! = 0 ) {
if ( e ! = ERANGE | | getgr_buf_len > = GETGR_R_SIZE_LIMIT ) {
2017-05-11 02:18:07 +03:00
rb_str_resize ( * getgr_tmp , 0 ) ;
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( e , " getgrnam_r " ) ;
2014-03-08 08:30:56 +04:00
}
rb_str_modify_expand ( * getgr_tmp , getgr_buf_len ) ;
getgr_buf = RSTRING_PTR ( * getgr_tmp ) ;
getgr_buf_len = rb_str_capacity ( * getgr_tmp ) ;
}
2014-10-11 17:33:14 +04:00
# elif defined(HAVE_GETGRNAM)
2012-03-28 11:40:02 +04:00
grptr = getgrnam ( grpname ) ;
2014-10-11 17:33:14 +04:00
# else
grptr = NULL ;
2012-03-28 11:40:02 +04:00
# endif
if ( ! grptr ) {
2013-04-27 19:38:36 +04:00
# if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
2012-03-28 11:40:02 +04:00
endgrent ( ) ;
# endif
2020-04-16 14:40:53 +03:00
rb_raise ( rb_eArgError , " can't find group for % " PRIsVALUE , id ) ;
2012-03-28 11:40:02 +04:00
}
gid = grptr - > gr_gid ;
2013-04-27 19:38:36 +04:00
# if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
2012-03-28 11:40:02 +04:00
endgrent ( ) ;
# endif
}
return gid ;
}
# ifdef p_gid_from_name
2013-06-02 07:12:04 +04:00
/*
* call - seq :
* Process : : GID . from_name ( name ) - > gid
*
* Get the group ID by the _name_ .
* If the group is not found , + ArgumentError + will be raised .
*
* Process : : GID . from_name ( " wheel " ) # = > 0
* Process : : GID . from_name ( " nosuchgroup " ) # = > can ' t find group for nosuchgroup ( ArgumentError )
*/
2012-03-28 11:40:02 +04:00
static VALUE
p_gid_from_name ( VALUE self , VALUE id )
{
return GIDT2NUM ( OBJ2GID ( id ) ) ;
}
# endif
# endif
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETUID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process : : Sys . setuid ( user ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Set the user ID of the current process to _user_ . Not
2004-01-02 09:01:12 +03:00
* available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setuid ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2012-03-28 11:40:02 +04:00
if ( setuid ( OBJ2UID ( id ) ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setuid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETRUID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process : : Sys . setruid ( user ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Set the real user ID of the calling process to _user_ .
2004-01-02 09:01:12 +03:00
* Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setruid ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2012-03-28 11:40:02 +04:00
if ( setruid ( OBJ2UID ( id ) ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setruid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETEUID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process : : Sys . seteuid ( user ) - > nil
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Set the effective user ID of the calling process to
2012-03-28 11:40:02 +04:00
* _user_ . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_seteuid ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2012-03-28 11:40:02 +04:00
if ( seteuid ( OBJ2UID ( id ) ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_seteuid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETREUID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : Sys . setreuid ( rid , eid ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Sets the ( user ) real and / or effective user IDs of the current
2004-01-02 09:01:12 +03:00
* process to _rid_ and _eid_ , respectively . A value of
* < code > - 1 < / code > for either means to leave that ID unchanged . Not
* available on all platforms .
*
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setreuid ( VALUE obj , VALUE rid , VALUE eid )
2003-07-23 06:39:46 +04:00
{
2014-03-08 07:55:01 +04:00
rb_uid_t ruid , euid ;
2012-03-28 11:40:02 +04:00
PREPARE_GETPWNAM ;
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2014-03-08 07:55:01 +04:00
ruid = OBJ2UID1 ( rid ) ;
euid = OBJ2UID1 ( eid ) ;
FINISH_GETPWNAM ;
if ( setreuid ( ruid , euid ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setreuid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETRESUID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : Sys . setresuid ( rid , eid , sid ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Sets the ( user ) real , effective , and saved user IDs of the
2004-06-29 05:17:39 +04:00
* current process to _rid_ , _eid_ , and _sid_ respectively . A
2004-01-02 09:01:12 +03:00
* value of < code > - 1 < / code > for any value means to
* leave that ID unchanged . Not available on all platforms .
*
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setresuid ( VALUE obj , VALUE rid , VALUE eid , VALUE sid )
2003-07-23 06:39:46 +04:00
{
2014-03-08 07:55:01 +04:00
rb_uid_t ruid , euid , suid ;
2012-03-28 11:40:02 +04:00
PREPARE_GETPWNAM ;
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2014-03-08 07:55:01 +04:00
ruid = OBJ2UID1 ( rid ) ;
euid = OBJ2UID1 ( eid ) ;
suid = OBJ2UID1 ( sid ) ;
FINISH_GETPWNAM ;
if ( setresuid ( ruid , euid , suid ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setresuid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . uid - > integer
* Process : : UID . rid - > integer
* Process : : Sys . getuid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the ( real ) user ID of this process .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . uid # = > 501
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_getuid ( VALUE obj )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t uid = getuid ( ) ;
return UIDT2NUM ( uid ) ;
1998-01-16 15:13:05 +03:00
}
2004-01-02 09:01:12 +03:00
2009-04-18 20:04:34 +04:00
# if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process . uid = user - > numeric
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Sets the ( user ) user ID for this process . Not available on all
2004-01-02 09:01:12 +03:00
* platforms .
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_setuid ( VALUE obj , VALUE id )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t uid ;
1998-01-16 15:13:05 +03:00
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
2012-03-28 11:40:02 +04:00
uid = OBJ2UID ( id ) ;
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESUID)
2001-09-08 18:17:53 +04:00
if ( setresuid ( uid , - 1 , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETREUID
2001-09-08 18:17:53 +04:00
if ( setreuid ( uid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETRUID
2001-09-08 18:17:53 +04:00
if ( setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETUID
1998-01-16 15:13:05 +03:00
{
2001-09-08 18:17:53 +04:00
if ( geteuid ( ) = = uid ) {
if ( setuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
}
else {
1998-01-16 15:13:05 +03:00
rb_notimplement ( ) ;
2001-09-08 18:17:53 +04:00
}
1998-01-16 15:13:05 +03:00
}
2003-07-23 06:39:46 +04:00
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return id ;
2003-07-23 06:39:46 +04:00
}
2009-04-18 20:04:34 +04:00
# else
# define proc_setuid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
/********************************************************************
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Document - class : Process : : UID
*
2019-03-28 06:33:35 +03:00
* The Process : : UID module contains a collection of
2004-01-02 09:01:12 +03:00
* module functions which can be used to portably get , set , and
* switch the current process ' s real , effective , and saved user IDs .
*
*/
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
static rb_uid_t SAVED_USER_ID = - 1 ;
2003-07-23 06:39:46 +04:00
2006-08-16 06:46:10 +04:00
# ifdef BROKEN_SETREUID
int
setreuid ( rb_uid_t ruid , rb_uid_t euid )
{
2012-04-03 13:33:40 +04:00
if ( ruid ! = ( rb_uid_t ) - 1 & & ruid ! = getuid ( ) ) {
if ( euid = = ( rb_uid_t ) - 1 ) euid = geteuid ( ) ;
2006-08-16 06:46:10 +04:00
if ( setuid ( ruid ) < 0 ) return - 1 ;
}
2012-04-03 13:33:40 +04:00
if ( euid ! = ( rb_uid_t ) - 1 & & euid ! = geteuid ( ) ) {
2006-08-16 06:46:10 +04:00
if ( seteuid ( euid ) < 0 ) return - 1 ;
}
return 0 ;
}
# endif
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : UID . change_privilege ( user ) - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Change the current process ' s real and effective user ID to that
2012-03-28 11:40:02 +04:00
* specified by _user_ . Returns the new user ID . Not
2004-01-02 09:01:12 +03:00
* available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* [ Process . uid , Process . euid ] # = > [ 0 , 0 ]
* Process : : UID . change_privilege ( 31 ) # = > 31
* [ Process . uid , Process . euid ] # = > [ 31 , 31 ]
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_uid_change_privilege ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t uid ;
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2003-08-29 12:34:14 +04:00
2012-03-28 11:40:02 +04:00
uid = OBJ2UID ( id ) ;
2003-07-23 06:39:46 +04:00
if ( geteuid ( ) = = 0 ) { /* root-user */
# if defined(HAVE_SETRESUID)
2003-07-23 20:07:35 +04:00
if ( setresuid ( uid , uid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETUID)
2003-07-23 20:07:35 +04:00
if ( setuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
2003-07-23 20:07:35 +04:00
if ( getuid ( ) = = uid ) {
if ( SAVED_USER_ID = = uid ) {
if ( setreuid ( - 1 , uid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( uid = = 0 ) { /* (r,e,s) == (root, root, x) */
if ( setreuid ( - 1 , SAVED_USER_ID ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setreuid ( SAVED_USER_ID , 0 ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = 0 ; /* (r,e,s) == (x, root, root) */
if ( setreuid ( uid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setreuid ( 0 , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = 0 ;
if ( setreuid ( uid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
}
}
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 06:39:46 +04:00
if ( setreuid ( uid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
}
# elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
2003-07-23 20:07:35 +04:00
if ( getuid ( ) = = uid ) {
if ( SAVED_USER_ID = = uid ) {
if ( seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( uid = = 0 ) {
if ( setruid ( SAVED_USER_ID ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = 0 ;
if ( setruid ( 0 ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setruid ( 0 ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = 0 ;
if ( seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
}
}
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 06:39:46 +04:00
if ( seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
}
# else
2013-01-15 18:07:20 +04:00
( void ) uid ;
2003-07-23 20:07:35 +04:00
rb_notimplement ( ) ;
2003-07-23 06:39:46 +04:00
# endif
2012-03-28 05:28:51 +04:00
}
else { /* unprivileged user */
2003-07-23 06:39:46 +04:00
# if defined(HAVE_SETRESUID)
2010-05-17 17:21:17 +04:00
if ( setresuid ( ( getuid ( ) = = uid ) ? ( rb_uid_t ) - 1 : uid ,
( geteuid ( ) = = uid ) ? ( rb_uid_t ) - 1 : uid ,
( SAVED_USER_ID = = uid ) ? ( rb_uid_t ) - 1 : uid ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
SAVED_USER_ID = uid ;
2003-07-23 20:07:35 +04:00
# elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
if ( SAVED_USER_ID = = uid ) {
2010-11-06 01:33:14 +03:00
if ( setreuid ( ( getuid ( ) = = uid ) ? ( rb_uid_t ) - 1 : uid ,
( geteuid ( ) = = uid ) ? ( rb_uid_t ) - 1 : uid ) < 0 )
rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else if ( getuid ( ) ! = uid ) {
2010-11-06 01:33:14 +03:00
if ( setreuid ( uid , ( geteuid ( ) = = uid ) ? ( rb_uid_t ) - 1 : uid ) < 0 )
rb_sys_fail ( 0 ) ;
2003-07-23 20:07:35 +04:00
SAVED_USER_ID = uid ;
2012-03-28 05:28:51 +04:00
}
else if ( /* getuid() = = uid & & */ geteuid ( ) ! = uid ) {
2003-07-23 20:07:35 +04:00
if ( setreuid ( geteuid ( ) , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
if ( setreuid ( uid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else { /* getuid() == uid && geteuid() == uid */
2003-07-23 20:07:35 +04:00
if ( setreuid ( - 1 , SAVED_USER_ID ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setreuid ( SAVED_USER_ID , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
if ( setreuid ( uid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
}
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
2003-07-23 20:07:35 +04:00
if ( SAVED_USER_ID = = uid ) {
if ( geteuid ( ) ! = uid & & seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( getuid ( ) ! = uid & & setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else if ( /* SAVED_USER_ID != uid && */ geteuid ( ) = = uid ) {
2003-07-23 20:07:35 +04:00
if ( getuid ( ) ! = uid ) {
if ( setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setruid ( SAVED_USER_ID ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
if ( setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
}
2012-03-28 05:28:51 +04:00
}
else if ( /* geteuid() ! = uid & & */ getuid ( ) = = uid ) {
2003-07-23 20:07:35 +04:00
if ( seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setruid ( SAVED_USER_ID ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
if ( setruid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 06:39:46 +04:00
}
# elif defined HAVE_44BSD_SETUID
2003-07-23 20:07:35 +04:00
if ( getuid ( ) = = uid ) {
/* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
if ( setuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 20:07:35 +04:00
}
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETEUID
2003-07-23 20:07:35 +04:00
if ( getuid ( ) = = uid & & SAVED_USER_ID = = uid ) {
if ( seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 20:07:35 +04:00
}
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETUID
2003-07-23 20:07:35 +04:00
if ( getuid ( ) = = uid & & SAVED_USER_ID = = uid ) {
if ( setuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 20:07:35 +04:00
}
2003-07-23 06:39:46 +04:00
# else
2003-07-23 20:07:35 +04:00
rb_notimplement ( ) ;
1998-01-16 15:13:05 +03:00
# endif
2003-07-23 06:39:46 +04:00
}
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return id ;
1998-01-16 15:13:05 +03:00
}
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process : : Sys . setgid ( group ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Set the group ID of the current process to _group_ . Not
2004-01-02 09:01:12 +03:00
* available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setgid ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2012-03-28 11:40:02 +04:00
if ( setgid ( OBJ2GID ( id ) ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setgid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETRGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process : : Sys . setrgid ( group ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Set the real group ID of the calling process to _group_ .
2004-01-02 09:01:12 +03:00
* Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setrgid ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2012-03-28 11:40:02 +04:00
if ( setrgid ( OBJ2GID ( id ) ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setrgid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETEGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process : : Sys . setegid ( group ) - > nil
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Set the effective group ID of the calling process to
2012-03-28 11:40:02 +04:00
* _group_ . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setegid ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2012-03-28 11:40:02 +04:00
if ( setegid ( OBJ2GID ( id ) ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setegid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETREGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : Sys . setregid ( rid , eid ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Sets the ( group ) real and / or effective group IDs of the current
2004-01-02 09:01:12 +03:00
* process to < em > rid < / em > and < em > eid < / em > , respectively . A value of
* < code > - 1 < / code > for either means to leave that ID unchanged . Not
* available on all platforms .
*
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setregid ( VALUE obj , VALUE rid , VALUE eid )
2003-07-23 06:39:46 +04:00
{
2014-03-08 07:55:01 +04:00
rb_gid_t rgid , egid ;
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2014-03-08 07:55:01 +04:00
rgid = OBJ2GID ( rid ) ;
egid = OBJ2GID ( eid ) ;
if ( setregid ( rgid , egid ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setregid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_SETRESGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : Sys . setresgid ( rid , eid , sid ) - > nil
2004-06-29 05:17:39 +04:00
*
2012-03-28 11:40:02 +04:00
* Sets the ( group ) real , effective , and saved user IDs of the
2004-01-02 09:01:12 +03:00
* current process to < em > rid < / em > , < em > eid < / em > , and < em > sid < / em >
* respectively . A value of < code > - 1 < / code > for any value means to
* leave that ID unchanged . Not available on all platforms .
*
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_setresgid ( VALUE obj , VALUE rid , VALUE eid , VALUE sid )
2003-07-23 06:39:46 +04:00
{
2014-03-08 07:55:01 +04:00
rb_gid_t rgid , egid , sgid ;
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2014-03-08 07:55:01 +04:00
rgid = OBJ2GID ( rid ) ;
egid = OBJ2GID ( eid ) ;
sgid = OBJ2GID ( sid ) ;
if ( setresgid ( rgid , egid , sgid ) ! = 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
return Qnil ;
}
2009-04-16 20:58:06 +04:00
# else
# define p_sys_setresgid rb_f_notimplement
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# if defined HAVE_ISSETUGID
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : Sys . issetugid - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if the process was created as a result
* of an execve ( 2 ) system call which had either of the setuid or
* setgid bits set ( and extra privileges were given as a result ) or
* if it has changed any of its real , effective or saved user or
* group IDs since it began execution .
*
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_sys_issetugid ( VALUE obj )
2003-07-23 06:39:46 +04:00
{
2022-01-15 17:07:32 +03:00
return RBOOL ( issetugid ( ) ) ;
2009-04-16 20:58:06 +04:00
}
2003-07-23 06:39:46 +04:00
# else
2009-04-16 20:58:06 +04:00
# define p_sys_issetugid rb_f_notimplement
2003-07-23 06:39:46 +04:00
# endif
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . gid - > integer
* Process : : GID . rid - > integer
* Process : : Sys . getgid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the ( real ) group ID for this process .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . gid # = > 500
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_getgid ( VALUE obj )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t gid = getgid ( ) ;
return GIDT2NUM ( gid ) ;
1998-01-16 15:13:05 +03:00
}
2004-01-02 09:01:12 +03:00
2009-04-18 20:04:34 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . gid = integer - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Sets the group ID for this process .
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_setgid ( VALUE obj , VALUE id )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t gid ;
1998-01-16 15:13:05 +03:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
2012-03-28 11:40:02 +04:00
gid = OBJ2GID ( id ) ;
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESGID)
2001-09-08 18:17:53 +04:00
if ( setresgid ( gid , - 1 , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETREGID
2001-09-08 18:17:53 +04:00
if ( setregid ( gid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETRGID
2006-08-16 06:46:10 +04:00
if ( setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETGID
1998-01-16 15:13:05 +03:00
{
2001-09-08 18:17:53 +04:00
if ( getegid ( ) = = gid ) {
if ( setgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
}
else {
1998-01-16 15:13:05 +03:00
rb_notimplement ( ) ;
2001-09-08 18:17:53 +04:00
}
1998-01-16 15:13:05 +03:00
}
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return GIDT2NUM ( gid ) ;
1998-01-16 15:13:05 +03:00
}
2009-04-18 20:04:34 +04:00
# else
# define proc_setgid rb_f_notimplement
# endif
1998-01-16 15:13:05 +03:00
2003-06-07 19:34:31 +04:00
2014-10-11 17:33:14 +04:00
# if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
2011-03-07 11:44:45 +03:00
/*
* Maximum supplementary groups are platform dependent .
* FWIW , 65536 is enough big for our supported OSs .
*
* OS Name max groups
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Linux Kernel > = 2.6 .3 65536
* Linux Kernel < 2.6 .3 32
* IBM AIX 5.2 64
* IBM AIX 5.3 . . . 6.1 128
* IBM AIX 7.1 128 ( can be configured to be up to 2048 )
* OpenBSD , NetBSD 16
* FreeBSD < 8.0 16
* FreeBSD > = 8.0 1023
* Darwin ( Mac OS X ) 16
* Sun Solaris 7 , 8 , 9 , 10 16
* Sun Solaris 11 / OpenSolaris 1024
* Windows 1015
*/
2011-03-07 14:58:12 +03:00
static int _maxgroups = - 1 ;
2012-06-27 09:37:15 +04:00
static int
get_sc_ngroups_max ( void )
2011-03-07 19:44:36 +03:00
{
# ifdef _SC_NGROUPS_MAX
return ( int ) sysconf ( _SC_NGROUPS_MAX ) ;
2011-03-08 17:29:22 +03:00
# elif defined(NGROUPS_MAX)
return ( int ) NGROUPS_MAX ;
2011-03-07 19:44:36 +03:00
# else
2011-03-10 19:26:01 +03:00
return - 1 ;
2011-03-07 19:44:36 +03:00
# endif
}
2012-06-27 09:37:15 +04:00
static int
maxgroups ( void )
2011-03-07 14:58:12 +03:00
{
if ( _maxgroups < 0 ) {
2011-03-07 19:44:36 +03:00
_maxgroups = get_sc_ngroups_max ( ) ;
2011-03-07 14:58:12 +03:00
if ( _maxgroups < 0 )
_maxgroups = RB_MAX_GROUPS ;
}
return _maxgroups ;
}
2011-03-10 19:54:02 +03:00
# endif
2011-03-07 14:58:12 +03:00
2003-06-07 19:34:31 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# ifdef HAVE_GETGROUPS
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . groups - > array
2004-06-29 05:17:39 +04:00
*
2019-03-28 06:33:35 +03:00
* Get an Array of the group IDs in the
2004-01-02 09:01:12 +03:00
* supplemental group access list for this process .
*
* Process . groups # = > [ 27 , 6 , 10 , 11 ]
*
2018-08-10 08:18:03 +03:00
* Note that this method is just a wrapper of getgroups ( 2 ) .
* This means that the following characteristics of
2018-10-12 23:01:52 +03:00
* the result completely depend on your system :
2018-08-10 08:18:03 +03:00
*
* - the result is sorted
* - the result includes effective GIDs
* - the result does not include duplicated GIDs
2022-01-19 05:50:04 +03:00
* - the result size does not exceed the value of Process . maxgroups
2018-08-10 08:18:03 +03:00
*
2018-10-12 23:01:52 +03:00
* You can make sure to get a sorted unique GID list of
2018-08-10 08:18:03 +03:00
* the current process by this expression :
*
2018-08-10 15:36:31 +03:00
* Process . groups . uniq . sort
2018-08-10 08:18:03 +03:00
*
2004-01-02 09:01:12 +03:00
*/
2003-06-07 19:34:31 +04:00
static VALUE
proc_getgroups ( VALUE obj )
{
2014-05-24 11:22:54 +04:00
VALUE ary , tmp ;
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
int i , ngroups ;
2005-05-14 18:57:53 +04:00
rb_gid_t * groups ;
2003-06-07 19:34:31 +04:00
2011-03-07 11:44:45 +03:00
ngroups = getgroups ( 0 , NULL ) ;
if ( ngroups = = - 1 )
rb_sys_fail ( 0 ) ;
2014-05-24 11:22:54 +04:00
groups = ALLOCV_N ( rb_gid_t , tmp , ngroups ) ;
2003-06-07 19:34:31 +04:00
2011-03-07 11:44:45 +03:00
ngroups = getgroups ( ngroups , groups ) ;
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
if ( ngroups = = - 1 )
2004-12-23 17:43:30 +03:00
rb_sys_fail ( 0 ) ;
2003-06-07 19:34:31 +04:00
ary = rb_ary_new ( ) ;
for ( i = 0 ; i < ngroups ; i + + )
2007-06-26 11:39:04 +04:00
rb_ary_push ( ary , GIDT2NUM ( groups [ i ] ) ) ;
2003-06-07 19:34:31 +04:00
2014-05-24 11:22:54 +04:00
ALLOCV_END ( tmp ) ;
2003-06-07 19:34:31 +04:00
return ary ;
2009-04-16 20:58:06 +04:00
}
2003-06-09 08:27:17 +04:00
# else
2009-04-16 20:58:06 +04:00
# define proc_getgroups rb_f_notimplement
2003-06-09 08:27:17 +04:00
# endif
2003-06-07 19:34:31 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# ifdef HAVE_SETGROUPS
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . groups = array - > array
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Set the supplemental group access list to the given
2019-03-28 06:33:35 +03:00
* Array of group IDs .
2004-01-02 09:01:12 +03:00
*
* Process . groups # = > [ 0 , 1 , 2 , 3 , 4 , 6 , 10 , 11 , 20 , 26 , 27 ]
* Process . groups = [ 27 , 6 , 10 , 11 ] # = > [ 27 , 6 , 10 , 11 ]
* Process . groups # = > [ 27 , 6 , 10 , 11 ]
*
*/
2003-06-07 19:34:31 +04:00
static VALUE
proc_setgroups ( VALUE obj , VALUE ary )
{
2011-03-07 15:54:27 +03:00
int ngroups , i ;
2005-05-14 18:57:53 +04:00
rb_gid_t * groups ;
2014-05-24 11:22:54 +04:00
VALUE tmp ;
2012-03-28 11:40:02 +04:00
PREPARE_GETGRNAM ;
2003-06-07 19:34:31 +04:00
Check_Type ( ary , T_ARRAY ) ;
2011-03-08 17:52:05 +03:00
ngroups = RARRAY_LENINT ( ary ) ;
if ( ngroups > maxgroups ( ) )
2011-03-07 15:54:27 +03:00
rb_raise ( rb_eArgError , " too many groups, %d max " , maxgroups ( ) ) ;
2003-06-07 19:34:31 +04:00
2014-05-24 11:22:54 +04:00
groups = ALLOCV_N ( rb_gid_t , tmp , ngroups ) ;
2003-06-07 19:34:31 +04:00
2011-03-07 15:54:27 +03:00
for ( i = 0 ; i < ngroups ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE g = RARRAY_AREF ( ary , i ) ;
2003-06-07 19:34:31 +04:00
2014-03-08 07:55:01 +04:00
groups [ i ] = OBJ2GID1 ( g ) ;
2003-06-07 19:34:31 +04:00
}
2014-03-08 07:55:01 +04:00
FINISH_GETGRNAM ;
2003-06-07 19:34:31 +04:00
2011-03-07 15:54:27 +03:00
if ( setgroups ( ngroups , groups ) = = - 1 ) /* ngroups <= maxgroups */
2004-12-23 17:43:30 +03:00
rb_sys_fail ( 0 ) ;
2003-06-07 19:34:31 +04:00
2014-05-24 11:22:54 +04:00
ALLOCV_END ( tmp ) ;
2003-06-07 19:34:31 +04:00
return proc_getgroups ( obj ) ;
2009-04-16 20:58:06 +04:00
}
2003-06-09 08:27:17 +04:00
# else
2009-04-16 20:58:06 +04:00
# define proc_setgroups rb_f_notimplement
2003-06-09 08:27:17 +04:00
# endif
2003-06-07 19:34:31 +04:00
2004-01-02 09:01:12 +03:00
2009-04-16 20:58:06 +04:00
# ifdef HAVE_INITGROUPS
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . initgroups ( username , gid ) - > array
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Initializes the supplemental group access list by reading the
* system group database and using all groups of which the given user
2022-01-19 05:50:04 +03:00
* is a member . The group with the specified _gid_ is also added to
* the list . Returns the resulting Array of the GIDs of all the
* groups in the supplementary group access list . Not available on
* all platforms .
2004-01-02 09:01:12 +03:00
*
* Process . groups # = > [ 0 , 1 , 2 , 3 , 4 , 6 , 10 , 11 , 20 , 26 , 27 ]
* Process . initgroups ( " mgranger " , 30 ) # = > [ 30 , 6 , 10 , 11 ]
* Process . groups # = > [ 30 , 6 , 10 , 11 ]
*
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_initgroups ( VALUE obj , VALUE uname , VALUE base_grp )
2003-07-23 06:39:46 +04:00
{
2017-10-11 09:16:03 +03:00
if ( initgroups ( StringValueCStr ( uname ) , OBJ2GID ( base_grp ) ) ! = 0 ) {
2003-07-23 06:39:46 +04:00
rb_sys_fail ( 0 ) ;
}
return proc_getgroups ( obj ) ;
2009-04-16 20:58:06 +04:00
}
2003-07-23 06:39:46 +04:00
# else
2009-04-16 20:58:06 +04:00
# define proc_initgroups rb_f_notimplement
2003-07-23 06:39:46 +04:00
# endif
2011-03-10 19:54:02 +03:00
# if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . maxgroups - > integer
2004-06-29 05:17:39 +04:00
*
2022-01-19 05:50:04 +03:00
* Returns the maximum number of GIDs allowed in the supplemental
2004-01-02 09:01:12 +03:00
* group access list .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . maxgroups # = > 32
*/
2003-06-07 19:34:31 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_getmaxgroups ( VALUE obj )
2003-06-07 19:34:31 +04:00
{
2011-03-07 14:58:12 +03:00
return INT2FIX ( maxgroups ( ) ) ;
2003-06-07 19:34:31 +04:00
}
2011-03-10 19:54:02 +03:00
# else
# define proc_getmaxgroups rb_f_notimplement
# endif
2003-06-07 19:34:31 +04:00
2011-03-10 19:54:02 +03:00
# ifdef HAVE_SETGROUPS
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . maxgroups = integer - > integer
2004-06-29 05:17:39 +04:00
*
2022-01-19 05:50:04 +03:00
* Sets the maximum number of GIDs allowed in the supplemental group
2004-01-02 09:01:12 +03:00
* access list .
*/
2003-06-07 19:34:31 +04:00
static VALUE
2005-08-31 05:40:56 +04:00
proc_setmaxgroups ( VALUE obj , VALUE val )
2003-06-07 19:34:31 +04:00
{
2011-03-07 11:44:45 +03:00
int ngroups = FIX2INT ( val ) ;
2011-03-07 19:44:36 +03:00
int ngroups_max = get_sc_ngroups_max ( ) ;
2011-03-06 17:28:02 +03:00
2011-03-07 11:44:45 +03:00
if ( ngroups < = 0 )
2019-12-20 03:19:39 +03:00
rb_raise ( rb_eArgError , " maxgroups %d should be positive " , ngroups ) ;
2011-03-07 11:44:45 +03:00
if ( ngroups > RB_MAX_GROUPS )
ngroups = RB_MAX_GROUPS ;
2003-06-07 19:34:31 +04:00
2011-03-07 14:58:12 +03:00
if ( ngroups_max > 0 & & ngroups > ngroups_max )
ngroups = ngroups_max ;
_maxgroups = ngroups ;
2003-06-07 19:34:31 +04:00
2011-03-07 14:58:12 +03:00
return INT2FIX ( _maxgroups ) ;
2003-06-07 19:34:31 +04:00
}
2011-03-10 19:54:02 +03:00
# else
# define proc_setmaxgroups rb_f_notimplement
# endif
2003-06-07 19:34:31 +04:00
2014-09-03 02:51:03 +04:00
# if defined(HAVE_DAEMON) || (defined(HAVE_WORKING_FORK) && defined(HAVE_SETSID))
2010-07-13 16:31:17 +04:00
static int rb_daemon ( int nochdir , int noclose ) ;
2004-08-17 13:02:40 +04:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process . daemon ( ) - > 0
* Process . daemon ( nochdir = nil , noclose = nil ) - > 0
2004-08-17 13:02:40 +04:00
*
* Detach the process from controlling terminal and run in
* the background as system daemon . Unless the argument
* nochdir is true ( i . e . non false ) , it changes the current
* working directory to the root ( " / " ) . Unless the argument
* noclose is true , daemon ( ) will redirect standard input ,
* standard output and standard error to / dev / null .
2010-03-30 09:00:15 +04:00
* Return zero on success , or raise one of Errno : : * .
2004-08-17 13:02:40 +04:00
*/
static VALUE
2019-08-28 11:48:48 +03:00
proc_daemon ( int argc , VALUE * argv , VALUE _ )
2004-08-17 13:02:40 +04:00
{
2016-04-14 07:41:47 +03:00
int n , nochdir = FALSE , noclose = FALSE ;
2004-08-17 13:02:40 +04:00
2016-04-14 07:41:47 +03:00
switch ( rb_check_arity ( argc , 0 , 2 ) ) {
2019-07-16 15:38:25 +03:00
case 2 : noclose = TO_BOOL ( argv [ 1 ] , " noclose " ) ;
case 1 : nochdir = TO_BOOL ( argv [ 0 ] , " nochdir " ) ;
2016-04-14 07:41:47 +03:00
}
2004-08-17 13:02:40 +04:00
2009-03-01 10:01:03 +03:00
prefork ( ) ;
2016-04-14 07:41:47 +03:00
n = rb_daemon ( nochdir , noclose ) ;
2004-08-17 13:02:40 +04:00
if ( n < 0 ) rb_sys_fail ( " daemon " ) ;
return INT2FIX ( n ) ;
2010-07-13 16:31:17 +04:00
}
static int
rb_daemon ( int nochdir , int noclose )
{
2011-06-24 12:06:38 +04:00
int err = 0 ;
# ifdef HAVE_DAEMON
2019-01-10 17:31:18 +03:00
if ( mjit_enabled ) mjit_pause ( false ) ; // Don't leave locked mutex to child.
2014-09-03 14:23:24 +04:00
before_fork_ruby ( ) ;
2011-06-24 12:06:38 +04:00
err = daemon ( nochdir , noclose ) ;
2018-11-20 03:04:19 +03:00
after_fork_ruby ( ) ;
rb_thread_atfork ( ) ; /* calls mjit_resume() */
2011-06-24 12:06:38 +04:00
# else
int n ;
2010-07-13 16:31:17 +04:00
2013-05-01 07:14:55 +04:00
# define fork_daemon() \
switch ( rb_fork_ruby ( NULL ) ) { \
case - 1 : return - 1 ; \
2021-07-15 10:41:54 +03:00
case 0 : break ; \
2013-05-01 07:14:55 +04:00
default : _exit ( EXIT_SUCCESS ) ; \
2004-08-17 13:02:40 +04:00
}
2013-05-01 07:14:55 +04:00
fork_daemon ( ) ;
if ( setsid ( ) < 0 ) return - 1 ;
2004-08-17 13:02:40 +04:00
2009-04-25 13:21:49 +04:00
/* must not be process-leader */
2013-05-01 07:14:55 +04:00
fork_daemon ( ) ;
2009-04-25 13:21:49 +04:00
2010-07-13 16:31:17 +04:00
if ( ! nochdir )
err = chdir ( " / " ) ;
2004-08-17 13:02:40 +04:00
2011-10-29 08:01:54 +04:00
if ( ! noclose & & ( n = rb_cloexec_open ( " /dev/null " , O_RDWR , 0 ) ) ! = - 1 ) {
rb_update_max_fd ( n ) ;
2004-12-23 17:43:30 +03:00
( void ) dup2 ( n , 0 ) ;
( void ) dup2 ( n , 1 ) ;
( void ) dup2 ( n , 2 ) ;
if ( n > 2 )
( void ) close ( n ) ;
2004-08-17 13:02:40 +04:00
}
2010-07-13 16:31:17 +04:00
# endif
2011-06-28 05:20:23 +04:00
return err ;
2011-06-24 12:06:38 +04:00
}
2009-04-16 20:58:06 +04:00
# else
# define proc_daemon rb_f_notimplement
# endif
2004-01-02 09:01:12 +03:00
/********************************************************************
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Document - class : Process : : GID
*
2019-03-28 06:33:35 +03:00
* The Process : : GID module contains a collection of
2004-01-02 09:01:12 +03:00
* module functions which can be used to portably get , set , and
* switch the current process ' s real , effective , and saved group IDs .
*
*/
2009-03-14 21:30:00 +03:00
static rb_gid_t SAVED_GROUP_ID = - 1 ;
2003-07-23 06:39:46 +04:00
2006-08-16 06:46:10 +04:00
# ifdef BROKEN_SETREGID
int
setregid ( rb_gid_t rgid , rb_gid_t egid )
{
2012-04-03 13:33:40 +04:00
if ( rgid ! = ( rb_gid_t ) - 1 & & rgid ! = getgid ( ) ) {
if ( egid = = ( rb_gid_t ) - 1 ) egid = getegid ( ) ;
2006-08-16 06:46:10 +04:00
if ( setgid ( rgid ) < 0 ) return - 1 ;
}
2012-04-03 13:33:40 +04:00
if ( egid ! = ( rb_gid_t ) - 1 & & egid ! = getegid ( ) ) {
2006-08-16 06:46:10 +04:00
if ( setegid ( egid ) < 0 ) return - 1 ;
}
return 0 ;
}
# endif
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : GID . change_privilege ( group ) - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Change the current process ' s real and effective group ID to that
2012-03-28 11:40:02 +04:00
* specified by _group_ . Returns the new group ID . Not
2004-01-02 09:01:12 +03:00
* available on all platforms .
*
* [ Process . gid , Process . egid ] # = > [ 0 , 0 ]
* Process : : GID . change_privilege ( 33 ) # = > 33
* [ Process . gid , Process . egid ] # = > [ 33 , 33 ]
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_gid_change_privilege ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t gid ;
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2003-08-29 12:34:14 +04:00
2012-03-28 11:40:02 +04:00
gid = OBJ2GID ( id ) ;
2003-07-23 06:39:46 +04:00
if ( geteuid ( ) = = 0 ) { /* root-user */
# if defined(HAVE_SETRESGID)
2003-07-23 20:07:35 +04:00
if ( setresgid ( gid , gid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETGID
2003-07-23 20:07:35 +04:00
if ( setgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
2003-07-23 20:07:35 +04:00
if ( getgid ( ) = = gid ) {
if ( SAVED_GROUP_ID = = gid ) {
if ( setregid ( - 1 , gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( gid = = 0 ) { /* (r,e,s) == (root, y, x) */
if ( setregid ( - 1 , SAVED_GROUP_ID ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setregid ( SAVED_GROUP_ID , 0 ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = 0 ; /* (r,e,s) == (x, root, root) */
if ( setregid ( gid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
2012-03-28 05:28:51 +04:00
}
else { /* (r,e,s) == (z, y, x) */
2003-07-23 20:07:35 +04:00
if ( setregid ( 0 , 0 ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = 0 ;
if ( setregid ( gid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
}
}
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 06:39:46 +04:00
if ( setregid ( gid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
}
# elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
2003-07-23 20:07:35 +04:00
if ( getgid ( ) = = gid ) {
if ( SAVED_GROUP_ID = = gid ) {
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( gid = = 0 ) {
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setrgid ( SAVED_GROUP_ID ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = 0 ;
if ( setrgid ( 0 ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setrgid ( 0 ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = 0 ;
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
}
}
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 06:39:46 +04:00
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
}
# else
2003-07-23 20:07:35 +04:00
rb_notimplement ( ) ;
2003-07-23 06:39:46 +04:00
# endif
2012-03-28 05:28:51 +04:00
}
else { /* unprivileged user */
2003-07-23 06:39:46 +04:00
# if defined(HAVE_SETRESGID)
2010-05-17 17:21:17 +04:00
if ( setresgid ( ( getgid ( ) = = gid ) ? ( rb_gid_t ) - 1 : gid ,
( getegid ( ) = = gid ) ? ( rb_gid_t ) - 1 : gid ,
( SAVED_GROUP_ID = = gid ) ? ( rb_gid_t ) - 1 : gid ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
SAVED_GROUP_ID = gid ;
2003-07-23 20:07:35 +04:00
# elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if ( SAVED_GROUP_ID = = gid ) {
2010-11-06 01:33:14 +03:00
if ( setregid ( ( getgid ( ) = = gid ) ? ( rb_uid_t ) - 1 : gid ,
( getegid ( ) = = gid ) ? ( rb_uid_t ) - 1 : gid ) < 0 )
rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else if ( getgid ( ) ! = gid ) {
2010-11-06 01:33:14 +03:00
if ( setregid ( gid , ( getegid ( ) = = gid ) ? ( rb_uid_t ) - 1 : gid ) < 0 )
rb_sys_fail ( 0 ) ;
2003-07-23 20:07:35 +04:00
SAVED_GROUP_ID = gid ;
2012-03-28 05:28:51 +04:00
}
else if ( /* getgid() = = gid & & */ getegid ( ) ! = gid ) {
2003-07-23 20:07:35 +04:00
if ( setregid ( getegid ( ) , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
if ( setregid ( gid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else { /* getgid() == gid && getegid() == gid */
2003-07-23 20:07:35 +04:00
if ( setregid ( - 1 , SAVED_GROUP_ID ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setregid ( SAVED_GROUP_ID , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
if ( setregid ( gid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
}
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
2003-07-23 20:07:35 +04:00
if ( SAVED_GROUP_ID = = gid ) {
if ( getegid ( ) ! = gid & & setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( getgid ( ) ! = gid & & setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else if ( /* SAVED_GROUP_ID != gid && */ getegid ( ) = = gid ) {
2003-07-23 20:07:35 +04:00
if ( getgid ( ) ! = gid ) {
if ( setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setrgid ( SAVED_GROUP_ID ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
if ( setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
2006-12-31 18:02:22 +03:00
}
2012-03-28 05:28:51 +04:00
else if ( /* getegid() ! = gid & & */ getgid ( ) = = gid ) {
2003-07-23 20:07:35 +04:00
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setrgid ( SAVED_GROUP_ID ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
if ( setrgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 06:39:46 +04:00
}
# elif defined HAVE_44BSD_SETGID
2003-07-23 20:07:35 +04:00
if ( getgid ( ) = = gid ) {
/* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
if ( setgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 20:07:35 +04:00
}
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETEGID
2003-07-23 20:07:35 +04:00
if ( getgid ( ) = = gid & & SAVED_GROUP_ID = = gid ) {
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 20:07:35 +04:00
}
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETGID
2003-07-23 20:07:35 +04:00
if ( getgid ( ) = = gid & & SAVED_GROUP_ID = = gid ) {
if ( setgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 20:07:35 +04:00
}
2003-07-23 06:39:46 +04:00
# else
2013-01-15 18:07:20 +04:00
( void ) gid ;
2003-07-23 20:07:35 +04:00
rb_notimplement ( ) ;
2003-07-23 06:39:46 +04:00
# endif
}
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return id ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . euid - > integer
* Process : : UID . eid - > integer
* Process : : Sys . geteuid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the effective user ID for this process .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . euid # = > 501
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_geteuid ( VALUE obj )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t euid = geteuid ( ) ;
2007-08-15 08:42:19 +04:00
return UIDT2NUM ( euid ) ;
1998-01-16 15:13:05 +03:00
}
2009-04-25 13:26:58 +04:00
# if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
2011-11-11 13:42:02 +04:00
static void
proc_seteuid ( rb_uid_t uid )
1998-01-16 15:13:05 +03:00
{
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESUID)
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( setresuid ( - 1 , uid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETREUID
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( setreuid ( - 1 , uid ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETEUID
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( seteuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETUID
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( uid = = getuid ( ) ) {
if ( setuid ( uid ) < 0 ) rb_sys_fail ( 0 ) ;
2001-09-08 18:17:53 +04:00
}
else {
1998-01-16 15:13:05 +03:00
rb_notimplement ( ) ;
2001-09-08 18:17:53 +04:00
}
2003-07-23 06:39:46 +04:00
# else
rb_notimplement ( ) ;
1998-01-16 15:13:05 +03:00
# endif
}
2009-04-25 13:26:58 +04:00
# endif
1998-01-16 15:13:05 +03:00
2009-04-18 20:41:16 +04:00
# if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
2011-11-11 13:42:02 +04:00
/*
* call - seq :
2012-03-28 11:40:02 +04:00
* Process . euid = user
2011-11-11 13:42:02 +04:00
*
* Sets the effective user ID for this process . Not available on all
* platforms .
*/
static VALUE
2011-12-05 14:02:02 +04:00
proc_seteuid_m ( VALUE mod , VALUE euid )
2011-11-11 13:42:02 +04:00
{
check_uid_switch ( ) ;
2012-03-28 11:40:02 +04:00
proc_seteuid ( OBJ2UID ( euid ) ) ;
2011-11-11 13:42:02 +04:00
return euid ;
}
2009-04-18 20:41:16 +04:00
# else
# define proc_seteuid_m rb_f_notimplement
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
static rb_uid_t
rb_seteuid_core ( rb_uid_t euid )
2003-07-23 06:39:46 +04:00
{
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t uid ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2003-08-29 12:34:14 +04:00
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
2003-07-23 06:39:46 +04:00
uid = getuid ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2003-07-23 06:39:46 +04:00
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESUID)
2003-07-23 06:39:46 +04:00
if ( uid ! = euid ) {
2003-07-23 20:07:35 +04:00
if ( setresuid ( - 1 , euid , euid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = euid ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setresuid ( - 1 , euid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
}
# elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
if ( setreuid ( - 1 , euid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( uid ! = euid ) {
2003-07-23 20:07:35 +04:00
if ( setreuid ( euid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setreuid ( uid , euid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = euid ;
2003-07-23 06:39:46 +04:00
}
# elif defined HAVE_SETEUID
if ( seteuid ( euid ) < 0 ) rb_sys_fail ( 0 ) ;
# elif defined HAVE_SETUID
if ( geteuid ( ) = = 0 ) rb_sys_fail ( 0 ) ;
if ( setuid ( euid ) < 0 ) rb_sys_fail ( 0 ) ;
# else
rb_notimplement ( ) ;
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return euid ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : UID . grant_privilege ( user ) - > integer
* Process : : UID . eid = user - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Set the effective user ID , and if possible , the saved user ID of
2012-03-28 11:40:02 +04:00
* the process to the given _user_ . Returns the new
2004-01-02 09:01:12 +03:00
* effective user ID . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* [ Process . uid , Process . euid ] # = > [ 0 , 0 ]
* Process : : UID . grant_privilege ( 31 ) # = > 31
* [ Process . uid , Process . euid ] # = > [ 0 , 31 ]
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_uid_grant_privilege ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2012-03-28 11:40:02 +04:00
rb_seteuid_core ( OBJ2UID ( id ) ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return id ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . egid - > integer
* Process : : GID . eid - > integer
* Process : : Sys . geteid - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns the effective group ID for this process . Not available on
* all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Process . egid # = > 500
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_getegid ( VALUE obj )
1998-01-16 15:13:05 +03:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t egid = getegid ( ) ;
2002-08-21 19:47:54 +04:00
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return GIDT2NUM ( egid ) ;
1998-01-16 15:13:05 +03:00
}
2009-04-25 14:28:25 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process . egid = integer - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Sets the effective group ID for this process . Not available on all
* platforms .
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
proc_setegid ( VALUE obj , VALUE egid )
1998-01-16 15:13:05 +03:00
{
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t gid ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
2012-03-28 11:40:02 +04:00
gid = OBJ2GID ( egid ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESGID)
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( setresgid ( - 1 , gid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETREGID
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( setregid ( - 1 , gid ) < 0 ) rb_sys_fail ( 0 ) ;
2001-01-10 10:30:18 +03:00
# elif defined HAVE_SETEGID
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( setegid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
# elif defined HAVE_SETGID
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
if ( gid = = getgid ( ) ) {
if ( setgid ( gid ) < 0 ) rb_sys_fail ( 0 ) ;
2001-09-08 18:17:53 +04:00
}
else {
1998-01-16 15:13:05 +03:00
rb_notimplement ( ) ;
2001-09-08 18:17:53 +04:00
}
2003-07-23 06:39:46 +04:00
# else
rb_notimplement ( ) ;
1998-01-16 15:13:05 +03:00
# endif
return egid ;
}
2009-04-25 14:28:25 +04:00
# endif
1998-01-16 15:13:05 +03:00
2009-04-18 20:41:16 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
# define proc_setegid_m proc_setegid
# else
# define proc_setegid_m rb_f_notimplement
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
static rb_gid_t
rb_setegid_core ( rb_gid_t egid )
2003-07-23 06:39:46 +04:00
{
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t gid ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2003-08-29 12:34:14 +04:00
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
2003-07-23 06:39:46 +04:00
gid = getgid ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2003-07-23 06:39:46 +04:00
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESGID)
2003-07-23 06:39:46 +04:00
if ( gid ! = egid ) {
2003-07-23 20:07:35 +04:00
if ( setresgid ( - 1 , egid , egid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = egid ;
2012-03-28 05:28:51 +04:00
}
else {
2003-07-23 20:07:35 +04:00
if ( setresgid ( - 1 , egid , - 1 ) < 0 ) rb_sys_fail ( 0 ) ;
2003-07-23 06:39:46 +04:00
}
# elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if ( setregid ( - 1 , egid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( gid ! = egid ) {
2003-07-23 20:07:35 +04:00
if ( setregid ( egid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
if ( setregid ( gid , egid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = egid ;
2003-07-23 06:39:46 +04:00
}
# elif defined HAVE_SETEGID
if ( setegid ( egid ) < 0 ) rb_sys_fail ( 0 ) ;
# elif defined HAVE_SETGID
if ( geteuid ( ) = = 0 /* root user */ ) rb_sys_fail ( 0 ) ;
if ( setgid ( egid ) < 0 ) rb_sys_fail ( 0 ) ;
# else
rb_notimplement ( ) ;
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return egid ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : GID . grant_privilege ( group ) - > integer
* Process : : GID . eid = group - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Set the effective group ID , and if possible , the saved group ID of
2012-03-28 11:40:02 +04:00
* the process to the given _group_ . Returns the new
2004-01-02 09:01:12 +03:00
* effective group ID . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* [ Process . gid , Process . egid ] # = > [ 0 , 0 ]
* Process : : GID . grant_privilege ( 31 ) # = > 33
* [ Process . gid , Process . egid ] # = > [ 0 , 33 ]
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_gid_grant_privilege ( VALUE obj , VALUE id )
2003-07-23 06:39:46 +04:00
{
2012-03-28 11:40:02 +04:00
rb_setegid_core ( OBJ2GID ( id ) ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return id ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : UID . re_exchangeable ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if the real and effective user IDs of a
* process may be exchanged on the current platform .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
2019-08-28 11:48:48 +03:00
p_uid_exchangeable ( VALUE _ )
2003-07-23 06:39:46 +04:00
{
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESUID)
2003-07-23 20:07:35 +04:00
return Qtrue ;
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
2003-07-23 20:07:35 +04:00
return Qtrue ;
2003-07-23 06:39:46 +04:00
# else
2003-07-23 20:07:35 +04:00
return Qfalse ;
2003-07-23 06:39:46 +04:00
# endif
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : UID . re_exchange - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Exchange real and effective user IDs and return the new effective
* user ID . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* [ Process . uid , Process . euid ] # = > [ 0 , 31 ]
* Process : : UID . re_exchange # = > 0
* [ Process . uid , Process . euid ] # = > [ 31 , 0 ]
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_uid_exchange ( VALUE obj )
2003-07-23 06:39:46 +04:00
{
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
rb_uid_t uid ;
# if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
rb_uid_t euid ;
# endif
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2003-08-29 12:34:14 +04:00
2003-07-23 06:39:46 +04:00
uid = getuid ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
2003-07-23 06:39:46 +04:00
euid = geteuid ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2003-07-23 06:39:46 +04:00
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESUID)
2003-07-23 06:39:46 +04:00
if ( setresuid ( euid , uid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
# elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
if ( setreuid ( euid , uid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_USER_ID = uid ;
# else
rb_notimplement ( ) ;
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return UIDT2NUM ( uid ) ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : GID . re_exchangeable ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if the real and effective group IDs of a
* process may be exchanged on the current platform .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
2019-08-28 11:48:48 +03:00
p_gid_exchangeable ( VALUE _ )
2003-07-23 06:39:46 +04:00
{
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESGID)
2003-07-23 20:07:35 +04:00
return Qtrue ;
2003-07-23 06:39:46 +04:00
# elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
2003-07-23 20:07:35 +04:00
return Qtrue ;
2003-07-23 06:39:46 +04:00
# else
2003-07-23 20:07:35 +04:00
return Qfalse ;
2003-07-23 06:39:46 +04:00
# endif
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : GID . re_exchange - > integer
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Exchange real and effective group IDs and return the new effective
* group ID . Not available on all platforms .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* [ Process . gid , Process . egid ] # = > [ 0 , 33 ]
* Process : : GID . re_exchange # = > 0
* [ Process . gid , Process . egid ] # = > [ 33 , 0 ]
*/
2003-07-23 06:39:46 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_gid_exchange ( VALUE obj )
2003-07-23 06:39:46 +04:00
{
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
rb_gid_t gid ;
# if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
rb_gid_t egid ;
# endif
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2003-08-29 12:34:14 +04:00
2003-07-23 06:39:46 +04:00
gid = getgid ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
2003-07-23 06:39:46 +04:00
egid = getegid ( ) ;
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
# endif
2003-07-23 06:39:46 +04:00
2009-06-22 16:23:06 +04:00
# if defined(HAVE_SETRESGID)
2003-07-23 06:39:46 +04:00
if ( setresgid ( egid , gid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
# elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if ( setregid ( egid , gid ) < 0 ) rb_sys_fail ( 0 ) ;
SAVED_GROUP_ID = gid ;
# else
rb_notimplement ( ) ;
# endif
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return GIDT2NUM ( gid ) ;
2003-07-23 06:39:46 +04:00
}
2004-01-02 09:01:12 +03:00
/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : UID . sid_available ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if the current platform has saved user
* ID functionality .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
2019-08-28 11:48:48 +03:00
p_uid_have_saved_id ( VALUE _ )
2003-07-23 06:39:46 +04:00
{
2003-08-01 22:51:10 +04:00
# if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
2003-07-23 20:07:35 +04:00
return Qtrue ;
2003-07-23 06:39:46 +04:00
# else
2003-07-23 20:07:35 +04:00
return Qfalse ;
2003-07-23 06:39:46 +04:00
# endif
}
2003-08-29 12:34:14 +04:00
# if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
static VALUE
2019-08-23 06:14:06 +03:00
p_uid_sw_ensure ( VALUE i )
2003-08-29 12:34:14 +04:00
{
2019-08-23 06:14:06 +03:00
rb_uid_t id = ( rb_uid_t /* narrowing */ ) i ;
2003-08-29 12:34:14 +04:00
under_uid_switch = 0 ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
id = rb_seteuid_core ( id ) ;
return UIDT2NUM ( id ) ;
2003-08-29 12:34:14 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : UID . switch - > integer
2010-05-18 01:07:33 +04:00
* Process : : UID . switch { | | block } - > object
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Switch the effective and real user IDs of the current process . If
* a < em > block < / em > is given , the user IDs will be switched back
* after the block is executed . Returns the new effective user ID if
* called without a block , and the return value of the block if one
* is given .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
p_uid_switch ( VALUE obj )
2003-07-23 06:39:46 +04:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t uid , euid ;
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2003-08-29 12:34:14 +04:00
2003-07-23 06:39:46 +04:00
uid = getuid ( ) ;
euid = geteuid ( ) ;
if ( uid ! = euid ) {
2011-11-11 13:42:02 +04:00
proc_seteuid ( uid ) ;
2003-07-23 20:07:35 +04:00
if ( rb_block_given_p ( ) ) {
2003-08-29 12:34:14 +04:00
under_uid_switch = 1 ;
return rb_ensure ( rb_yield , Qnil , p_uid_sw_ensure , SAVED_USER_ID ) ;
2012-03-28 05:28:51 +04:00
}
else {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return UIDT2NUM ( euid ) ;
2003-07-23 20:07:35 +04:00
}
2012-03-28 05:28:51 +04:00
}
else if ( euid ! = SAVED_USER_ID ) {
2011-11-11 13:42:02 +04:00
proc_seteuid ( SAVED_USER_ID ) ;
2003-07-23 20:07:35 +04:00
if ( rb_block_given_p ( ) ) {
2003-08-29 12:34:14 +04:00
under_uid_switch = 1 ;
return rb_ensure ( rb_yield , Qnil , p_uid_sw_ensure , euid ) ;
2012-03-28 05:28:51 +04:00
}
else {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return UIDT2NUM ( uid ) ;
2003-07-23 20:07:35 +04:00
}
2012-03-28 05:28:51 +04:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 06:39:46 +04:00
}
2012-04-14 03:45:37 +04:00
2018-07-24 08:38:07 +03:00
UNREACHABLE_RETURN ( Qnil ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
}
2003-07-23 06:39:46 +04:00
# else
2003-08-29 12:34:14 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_uid_sw_ensure ( VALUE obj )
2003-08-29 12:34:14 +04:00
{
under_uid_switch = 0 ;
return p_uid_exchange ( obj ) ;
}
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_uid_switch ( VALUE obj )
2003-08-29 12:34:14 +04:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_uid_t uid , euid ;
2003-08-29 12:34:14 +04:00
2003-11-04 12:13:57 +03:00
check_uid_switch ( ) ;
2003-08-29 12:34:14 +04:00
uid = getuid ( ) ;
euid = geteuid ( ) ;
2003-07-23 06:39:46 +04:00
if ( uid = = euid ) {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 06:39:46 +04:00
}
2003-08-29 12:34:14 +04:00
p_uid_exchange ( obj ) ;
2003-07-23 06:39:46 +04:00
if ( rb_block_given_p ( ) ) {
2003-08-29 12:34:14 +04:00
under_uid_switch = 1 ;
return rb_ensure ( rb_yield , Qnil , p_uid_sw_ensure , obj ) ;
2012-03-28 05:28:51 +04:00
}
else {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return UIDT2NUM ( euid ) ;
2003-07-23 06:39:46 +04:00
}
}
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* Process : : GID . sid_available ? - > true or false
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Returns + true + if the current platform has saved group
* ID functionality .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
2019-08-28 11:48:48 +03:00
p_gid_have_saved_id ( VALUE _ )
2003-07-23 06:39:46 +04:00
{
2003-08-01 22:51:10 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
2003-07-23 20:07:35 +04:00
return Qtrue ;
2003-07-23 06:39:46 +04:00
# else
2003-07-23 20:07:35 +04:00
return Qfalse ;
2003-07-23 06:39:46 +04:00
# endif
}
2003-08-29 12:34:14 +04:00
# if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
static VALUE
2019-08-23 06:14:06 +03:00
p_gid_sw_ensure ( VALUE i )
2003-08-29 12:34:14 +04:00
{
2019-08-23 06:14:06 +03:00
rb_gid_t id = ( rb_gid_t /* narrowing */ ) i ;
2003-08-29 12:34:14 +04:00
under_gid_switch = 0 ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
id = rb_setegid_core ( id ) ;
return GIDT2NUM ( id ) ;
2003-08-29 12:34:14 +04:00
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2016-09-08 07:57:49 +03:00
* Process : : GID . switch - > integer
2010-05-18 01:07:33 +04:00
* Process : : GID . switch { | | block } - > object
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* Switch the effective and real group IDs of the current process . If
* a < em > block < / em > is given , the group IDs will be switched back
* after the block is executed . Returns the new effective group ID if
* called without a block , and the return value of the block if one
* is given .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
*/
2003-07-23 06:39:46 +04:00
static VALUE
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
p_gid_switch ( VALUE obj )
2003-07-23 06:39:46 +04:00
{
2009-03-14 21:30:00 +03:00
rb_gid_t gid , egid ;
2003-07-23 06:39:46 +04:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2003-08-29 12:34:14 +04:00
2003-07-23 06:39:46 +04:00
gid = getgid ( ) ;
egid = getegid ( ) ;
if ( gid ! = egid ) {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
proc_setegid ( obj , GIDT2NUM ( gid ) ) ;
2003-07-23 20:07:35 +04:00
if ( rb_block_given_p ( ) ) {
2003-08-29 12:34:14 +04:00
under_gid_switch = 1 ;
return rb_ensure ( rb_yield , Qnil , p_gid_sw_ensure , SAVED_GROUP_ID ) ;
2012-03-28 05:28:51 +04:00
}
else {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return GIDT2NUM ( egid ) ;
2003-07-23 20:07:35 +04:00
}
2009-03-14 21:30:00 +03:00
}
else if ( egid ! = SAVED_GROUP_ID ) {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
proc_setegid ( obj , GIDT2NUM ( SAVED_GROUP_ID ) ) ;
2003-07-23 20:07:35 +04:00
if ( rb_block_given_p ( ) ) {
2003-08-29 12:34:14 +04:00
under_gid_switch = 1 ;
return rb_ensure ( rb_yield , Qnil , p_gid_sw_ensure , egid ) ;
2012-03-28 05:28:51 +04:00
}
else {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return GIDT2NUM ( gid ) ;
2003-07-23 20:07:35 +04:00
}
2009-03-14 21:30:00 +03:00
}
else {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 06:39:46 +04:00
}
2012-04-14 03:45:37 +04:00
2018-07-24 08:38:07 +03:00
UNREACHABLE_RETURN ( Qnil ) ;
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
}
2003-07-23 06:39:46 +04:00
# else
2003-08-31 17:29:54 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_gid_sw_ensure ( VALUE obj )
2003-08-29 12:34:14 +04:00
{
under_gid_switch = 0 ;
2003-08-31 17:57:38 +04:00
return p_gid_exchange ( obj ) ;
2003-08-29 12:34:14 +04:00
}
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
p_gid_switch ( VALUE obj )
2003-08-29 12:34:14 +04:00
{
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
rb_gid_t gid , egid ;
2003-08-29 12:34:14 +04:00
2003-11-04 12:13:57 +03:00
check_gid_switch ( ) ;
2003-08-29 12:34:14 +04:00
gid = getgid ( ) ;
egid = getegid ( ) ;
2003-07-23 06:39:46 +04:00
if ( gid = = egid ) {
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EPERM , 0 ) ;
2003-07-23 06:39:46 +04:00
}
2003-08-29 12:34:14 +04:00
p_gid_exchange ( obj ) ;
2003-07-23 06:39:46 +04:00
if ( rb_block_given_p ( ) ) {
2003-08-29 12:34:14 +04:00
under_gid_switch = 1 ;
return rb_ensure ( rb_yield , Qnil , p_gid_sw_ensure , obj ) ;
2012-03-28 05:28:51 +04:00
}
else {
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
return GIDT2NUM ( egid ) ;
2003-07-23 06:39:46 +04:00
}
}
* configure.in (pid_t, uid_t, gid_t): check if defined.
* intern.h, process.c, rubyio.h, ext/etc/etc.c, ext/pty/pty.c: use
rb_{pid,uid,gid}_t instead of plain int. [ruby-dev:30376]
* ext/etc/extconf.rb (PIDT2NUM, NUM2PIDT, UIDT2NUM, NUM2UIDT, GIDT2NUM,
NUM2GIDT): moved to configure.in.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-18 07:11:57 +03:00
# endif
2003-07-23 06:39:46 +04:00
2004-01-02 09:01:12 +03:00
2009-06-22 16:23:06 +04:00
# if defined(HAVE_TIMES)
2013-08-21 15:36:43 +04:00
static long
get_clk_tck ( void )
{
# ifdef HAVE__SC_CLK_TCK
2018-01-17 14:22:14 +03:00
return sysconf ( _SC_CLK_TCK ) ;
# elif defined CLK_TCK
return CLK_TCK ;
# elif defined HZ
return HZ ;
2013-08-21 15:36:43 +04:00
# else
2018-01-17 14:22:14 +03:00
return 60 ;
2013-08-21 15:36:43 +04:00
# endif
}
2004-01-02 09:01:12 +03:00
/*
* call - seq :
2013-10-27 05:38:20 +04:00
* Process . times - > aProcessTms
2004-06-29 05:17:39 +04:00
*
2019-03-28 06:33:35 +03:00
* Returns a < code > Tms < / code > structure ( see Process : : Tms )
2011-05-14 12:47:02 +04:00
* that contains user and system CPU times for this process ,
* and also for children processes .
2004-06-29 05:17:39 +04:00
*
2004-01-02 09:01:12 +03:00
* t = Process . times
2011-05-14 12:47:02 +04:00
* [ t . utime , t . stime , t . cutime , t . cstime ] # = > [ 0.0 , 0.02 , 0.00 , 0.00 ]
2004-01-02 09:01:12 +03:00
*/
2001-02-16 10:53:21 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_proc_times ( VALUE obj )
2001-02-16 10:53:21 +03:00
{
process.c: Use getrusage(2) in Process.times
if getrusage(2) is available, to improve precision of Process.times and
its user like lib/benchmark.rb.
On macOS, since getrusage(2) has better precision than times(3),
they are much improved like:
* Before
Process.times
=> #<struct Process::Tms utime=0.56, stime=0.35, cutime=0.04, cstime=0.03>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.340000 0.310000 0.650000 ( 0.674025)
* After
Process.times
=> #<struct Process::Tms utime=0.561899, stime=0.35076, cutime=0.046483, cstime=0.038929>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.343223 0.310037 0.653260 ( 0.674025)
On Linux, since struct rusage from getrusage(2) is used instead of struct tms
from times(2), they are slightly improved like:
* Before
Process.times
=> #<struct Process::Tms utime=0.43, stime=0.11, cutime=0.0, cstime=0.0>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.120000 0.040000 0.170000 ( 0.171621)
* After
Process.times
=> #<struct Process::Tms utime=0.432, stime=0.116, cutime=0.0, cstime=0.0>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.124000 0.048000 0.172000 ( 0.171621)
[ruby-dev:49471] [Feature #11952]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58935 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-05-28 04:48:11 +03:00
VALUE utime , stime , cutime , cstime , ret ;
# if defined(RUSAGE_SELF) && defined(RUSAGE_CHILDREN)
struct rusage usage_s , usage_c ;
if ( getrusage ( RUSAGE_SELF , & usage_s ) ! = 0 | | getrusage ( RUSAGE_CHILDREN , & usage_c ) ! = 0 )
rb_sys_fail ( " getrusage " ) ;
utime = DBL2NUM ( ( double ) usage_s . ru_utime . tv_sec + ( double ) usage_s . ru_utime . tv_usec / 1e6 ) ;
stime = DBL2NUM ( ( double ) usage_s . ru_stime . tv_sec + ( double ) usage_s . ru_stime . tv_usec / 1e6 ) ;
cutime = DBL2NUM ( ( double ) usage_c . ru_utime . tv_sec + ( double ) usage_c . ru_utime . tv_usec / 1e6 ) ;
cstime = DBL2NUM ( ( double ) usage_c . ru_stime . tv_sec + ( double ) usage_c . ru_stime . tv_usec / 1e6 ) ;
# else
2018-01-17 14:16:24 +03:00
const double hertz = ( double ) get_clk_tck ( ) ;
2001-02-16 10:53:21 +03:00
struct tms buf ;
2001-05-21 08:22:54 +04:00
times ( & buf ) ;
2013-08-21 16:05:29 +04:00
utime = DBL2NUM ( buf . tms_utime / hertz ) ;
stime = DBL2NUM ( buf . tms_stime / hertz ) ;
cutime = DBL2NUM ( buf . tms_cutime / hertz ) ;
cstime = DBL2NUM ( buf . tms_cstime / hertz ) ;
process.c: Use getrusage(2) in Process.times
if getrusage(2) is available, to improve precision of Process.times and
its user like lib/benchmark.rb.
On macOS, since getrusage(2) has better precision than times(3),
they are much improved like:
* Before
Process.times
=> #<struct Process::Tms utime=0.56, stime=0.35, cutime=0.04, cstime=0.03>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.340000 0.310000 0.650000 ( 0.674025)
* After
Process.times
=> #<struct Process::Tms utime=0.561899, stime=0.35076, cutime=0.046483, cstime=0.038929>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.343223 0.310037 0.653260 ( 0.674025)
On Linux, since struct rusage from getrusage(2) is used instead of struct tms
from times(2), they are slightly improved like:
* Before
Process.times
=> #<struct Process::Tms utime=0.43, stime=0.11, cutime=0.0, cstime=0.0>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.120000 0.040000 0.170000 ( 0.171621)
* After
Process.times
=> #<struct Process::Tms utime=0.432, stime=0.116, cutime=0.0, cstime=0.0>
puts Benchmark.measure { "a" * 1_000_000_000 }
0.124000 0.048000 0.172000 ( 0.171621)
[ruby-dev:49471] [Feature #11952]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58935 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-05-28 04:48:11 +03:00
# endif
2013-08-21 16:05:29 +04:00
ret = rb_struct_new ( rb_cProcessTms , utime , stime , cutime , cstime ) ;
RB_GC_GUARD ( utime ) ;
RB_GC_GUARD ( stime ) ;
RB_GC_GUARD ( cutime ) ;
RB_GC_GUARD ( cstime ) ;
return ret ;
2009-04-16 20:58:06 +04:00
}
2001-02-16 10:53:21 +03:00
# else
2009-04-16 20:58:06 +04:00
# define rb_proc_times rb_f_notimplement
2001-02-16 10:53:21 +03:00
# endif
2013-08-23 16:06:02 +04:00
# ifdef HAVE_LONG_LONG
typedef LONG_LONG timetick_int_t ;
# define TIMETICK_INT_MIN LLONG_MIN
# define TIMETICK_INT_MAX LLONG_MAX
# define TIMETICK_INT2NUM(v) LL2NUM(v)
2017-03-06 09:04:52 +03:00
# define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_LONG_P(a, b)
2013-08-23 16:06:02 +04:00
# else
typedef long timetick_int_t ;
# define TIMETICK_INT_MIN LONG_MIN
# define TIMETICK_INT_MAX LONG_MAX
# define TIMETICK_INT2NUM(v) LONG2NUM(v)
2017-03-06 09:04:52 +03:00
# define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_P(a, b)
2013-08-23 16:06:02 +04:00
# endif
2016-05-08 20:44:51 +03:00
CONSTFUNC ( static timetick_int_t gcd_timetick_int ( timetick_int_t , timetick_int_t ) ) ;
2013-08-23 16:06:02 +04:00
static timetick_int_t
2013-08-26 05:39:19 +04:00
gcd_timetick_int ( timetick_int_t a , timetick_int_t b )
2013-08-22 01:27:44 +04:00
{
2013-08-23 16:06:02 +04:00
timetick_int_t t ;
2013-08-22 01:27:44 +04:00
2013-08-23 14:44:33 +04:00
if ( a < b ) {
t = a ;
a = b ;
b = t ;
2013-08-22 01:27:44 +04:00
}
2013-08-23 14:44:33 +04:00
while ( 1 ) {
t = a % b ;
if ( t = = 0 )
return b ;
a = b ;
b = t ;
2013-08-22 01:27:44 +04:00
}
2013-08-23 14:44:33 +04:00
}
static void
2013-08-23 16:06:02 +04:00
reduce_fraction ( timetick_int_t * np , timetick_int_t * dp )
2013-08-23 14:44:33 +04:00
{
2013-08-26 05:39:19 +04:00
timetick_int_t gcd = gcd_timetick_int ( * np , * dp ) ;
2013-08-23 14:44:33 +04:00
if ( gcd ! = 1 ) {
* np / = gcd ;
* dp / = gcd ;
2013-08-22 01:27:44 +04:00
}
2013-08-23 14:44:33 +04:00
}
2013-08-23 16:46:06 +04:00
static void
reduce_factors ( timetick_int_t * numerators , int num_numerators ,
timetick_int_t * denominators , int num_denominators )
{
int i , j ;
for ( i = 0 ; i < num_numerators ; i + + ) {
if ( numerators [ i ] = = 1 )
continue ;
for ( j = 0 ; j < num_denominators ; j + + ) {
if ( denominators [ j ] = = 1 )
continue ;
reduce_fraction ( & numerators [ i ] , & denominators [ j ] ) ;
}
}
}
2013-08-23 14:44:33 +04:00
struct timetick {
2013-08-23 16:06:02 +04:00
timetick_int_t giga_count ;
int32_t count ; /* 0 .. 999999999 */
2013-08-23 14:44:33 +04:00
} ;
2013-08-23 16:06:02 +04:00
static VALUE
2013-08-23 16:46:06 +04:00
timetick2dblnum ( struct timetick * ttp ,
timetick_int_t * numerators , int num_numerators ,
timetick_int_t * denominators , int num_denominators )
2013-08-23 14:44:33 +04:00
{
2013-08-23 16:46:06 +04:00
double d ;
int i ;
reduce_factors ( numerators , num_numerators ,
denominators , num_denominators ) ;
d = ttp - > giga_count * 1e9 + ttp - > count ;
for ( i = 0 ; i < num_numerators ; i + + )
d * = numerators [ i ] ;
for ( i = 0 ; i < num_denominators ; i + + )
d / = denominators [ i ] ;
return DBL2NUM ( d ) ;
2013-08-23 14:44:33 +04:00
}
2013-08-31 17:21:48 +04:00
static VALUE
timetick2dblnum_reciprocal ( struct timetick * ttp ,
timetick_int_t * numerators , int num_numerators ,
timetick_int_t * denominators , int num_denominators )
{
double d ;
int i ;
reduce_factors ( numerators , num_numerators ,
denominators , num_denominators ) ;
d = 1.0 ;
for ( i = 0 ; i < num_denominators ; i + + )
d * = denominators [ i ] ;
for ( i = 0 ; i < num_numerators ; i + + )
d / = numerators [ i ] ;
d / = ttp - > giga_count * 1e9 + ttp - > count ;
return DBL2NUM ( d ) ;
}
2013-08-23 14:44:33 +04:00
# define NDIV(x,y) (-(-((x)+1) / (y))-1)
# define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n) / (d))
2013-08-22 01:27:44 +04:00
2013-08-23 14:44:33 +04:00
static VALUE
2013-08-23 16:46:06 +04:00
timetick2integer ( struct timetick * ttp ,
timetick_int_t * numerators , int num_numerators ,
timetick_int_t * denominators , int num_denominators )
2013-08-23 14:44:33 +04:00
{
VALUE v ;
2013-08-23 16:46:06 +04:00
int i ;
2013-08-22 01:27:44 +04:00
2013-08-23 16:46:06 +04:00
reduce_factors ( numerators , num_numerators ,
denominators , num_denominators ) ;
2013-08-23 14:44:33 +04:00
2013-08-23 16:06:02 +04:00
if ( ! MUL_OVERFLOW_SIGNED_INTEGER_P ( 1000000000 , ttp - > giga_count ,
TIMETICK_INT_MIN , TIMETICK_INT_MAX - ttp - > count ) ) {
timetick_int_t t = ttp - > giga_count * 1000000000 + ttp - > count ;
2013-08-23 16:46:06 +04:00
for ( i = 0 ; i < num_numerators ; i + + ) {
timetick_int_t factor = numerators [ i ] ;
2017-03-06 09:04:52 +03:00
if ( MUL_OVERFLOW_TIMETICK_P ( factor , t ) )
2013-08-23 16:46:06 +04:00
goto generic ;
t * = factor ;
}
for ( i = 0 ; i < num_denominators ; i + + ) {
t = DIV ( t , denominators [ i ] ) ;
2013-08-23 14:44:33 +04:00
}
2013-08-23 16:46:06 +04:00
return TIMETICK_INT2NUM ( t ) ;
2013-08-22 01:27:44 +04:00
}
2013-08-23 14:44:33 +04:00
2013-08-23 16:46:06 +04:00
generic :
2013-08-23 16:06:02 +04:00
v = TIMETICK_INT2NUM ( ttp - > giga_count ) ;
2013-08-23 14:44:33 +04:00
v = rb_funcall ( v , ' * ' , 1 , LONG2FIX ( 1000000000 ) ) ;
v = rb_funcall ( v , ' + ' , 1 , LONG2FIX ( ttp - > count ) ) ;
2013-08-23 16:46:06 +04:00
for ( i = 0 ; i < num_numerators ; i + + ) {
timetick_int_t factor = numerators [ i ] ;
if ( factor = = 1 )
continue ;
v = rb_funcall ( v , ' * ' , 1 , TIMETICK_INT2NUM ( factor ) ) ;
}
for ( i = 0 ; i < num_denominators ; i + + ) {
v = rb_funcall ( v , ' / ' , 1 , TIMETICK_INT2NUM ( denominators [ i ] ) ) ; /* Ruby's '/' is div. */
}
2013-08-23 14:44:33 +04:00
return v ;
}
static VALUE
2013-08-23 16:46:06 +04:00
make_clock_result ( struct timetick * ttp ,
timetick_int_t * numerators , int num_numerators ,
timetick_int_t * denominators , int num_denominators ,
VALUE unit )
{
2014-11-24 06:44:24 +03:00
if ( unit = = ID2SYM ( id_nanosecond ) ) {
2013-08-23 16:46:06 +04:00
numerators [ num_numerators + + ] = 1000000000 ;
return timetick2integer ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2014-11-24 06:44:24 +03:00
else if ( unit = = ID2SYM ( id_microsecond ) ) {
2013-08-23 16:46:06 +04:00
numerators [ num_numerators + + ] = 1000000 ;
return timetick2integer ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2014-11-24 06:44:24 +03:00
else if ( unit = = ID2SYM ( id_millisecond ) ) {
2013-08-23 16:46:06 +04:00
numerators [ num_numerators + + ] = 1000 ;
return timetick2integer ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2014-11-24 06:44:24 +03:00
else if ( unit = = ID2SYM ( id_second ) ) {
2013-12-16 09:04:03 +04:00
return timetick2integer ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2014-11-24 06:44:24 +03:00
else if ( unit = = ID2SYM ( id_float_microsecond ) ) {
2013-08-23 16:46:06 +04:00
numerators [ num_numerators + + ] = 1000000 ;
return timetick2dblnum ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2014-11-24 06:44:24 +03:00
else if ( unit = = ID2SYM ( id_float_millisecond ) ) {
2013-08-23 16:46:06 +04:00
numerators [ num_numerators + + ] = 1000 ;
return timetick2dblnum ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2014-11-24 06:44:24 +03:00
else if ( NIL_P ( unit ) | | unit = = ID2SYM ( id_float_second ) ) {
2013-08-23 16:46:06 +04:00
return timetick2dblnum ( ttp , numerators , num_numerators , denominators , num_denominators ) ;
}
2013-08-23 14:44:33 +04:00
else
rb_raise ( rb_eArgError , " unexpected unit: % " PRIsVALUE , unit ) ;
2013-08-22 01:27:44 +04:00
}
2013-09-01 19:09:06 +04:00
# ifdef __APPLE__
2018-06-17 02:22:42 +03:00
static const mach_timebase_info_data_t *
2013-09-01 19:09:06 +04:00
get_mach_timebase_info ( void )
{
static mach_timebase_info_data_t sTimebaseInfo ;
if ( sTimebaseInfo . denom = = 0 ) {
( void ) mach_timebase_info ( & sTimebaseInfo ) ;
}
return & sTimebaseInfo ;
}
2018-06-17 02:22:42 +03:00
double
ruby_real_ms_time ( void )
{
const mach_timebase_info_data_t * info = get_mach_timebase_info ( ) ;
uint64_t t = mach_absolute_time ( ) ;
return ( double ) t * info - > numer / info - > denom / 1e6 ;
}
2013-09-01 19:09:06 +04:00
# endif
2022-02-18 11:59:15 +03:00
# if defined(NUM2CLOCKID)
# define NUMERIC_CLOCKID 1
# else
# define NUMERIC_CLOCKID 0
# define NUM2CLOCKID(x) 0
# endif
2013-08-11 06:59:30 +04:00
/*
* call - seq :
2013-08-12 08:48:28 +04:00
* Process . clock_gettime ( clock_id [ , unit ] ) - > number
2013-08-11 06:59:30 +04:00
*
* Returns a time returned by POSIX clock_gettime ( ) function .
*
2013-08-24 06:01:07 +04:00
* p Process . clock_gettime ( Process : : CLOCK_MONOTONIC )
* # = > 896053.968060096
*
2013-08-12 08:48:28 +04:00
* + clock_id + specifies a kind of clock .
2015-12-14 05:52:14 +03:00
* It is specified as a constant which begins with < code > Process : : CLOCK_ < / code >
2013-08-12 08:48:28 +04:00
* such as Process : : CLOCK_REALTIME and Process : : CLOCK_MONOTONIC .
*
2013-08-11 06:59:30 +04:00
* The supported constants depends on OS and version .
2013-08-12 08:48:28 +04:00
* Ruby provides following types of + clock_id + if available .
2013-08-11 06:59:30 +04:00
*
2021-08-26 14:38:01 +03:00
* [ CLOCK_REALTIME ] SUSv2 to 4 , Linux 2.5 .63 , FreeBSD 3.0 , NetBSD 2.0 , OpenBSD 2.1 , macOS 10.12 , Windows - 8 / Server - 2012
* [ CLOCK_MONOTONIC ] SUSv3 to 4 , Linux 2.5 .63 , FreeBSD 3.0 , NetBSD 2.0 , OpenBSD 3.4 , macOS 10.12 , Windows - 2000
2019-09-05 02:33:43 +03:00
* [ CLOCK_PROCESS_CPUTIME_ID ] SUSv3 to 4 , Linux 2.5 .63 , FreeBSD 9.3 , OpenBSD 5.4 , macOS 10.12
2016-09-21 11:46:06 +03:00
* [ CLOCK_THREAD_CPUTIME_ID ] SUSv3 to 4 , Linux 2.5 .63 , FreeBSD 7.1 , OpenBSD 5.4 , macOS 10.12
2013-08-11 06:59:30 +04:00
* [ CLOCK_VIRTUAL ] FreeBSD 3.0 , OpenBSD 2.1
* [ CLOCK_PROF ] FreeBSD 3.0 , OpenBSD 2.1
* [ CLOCK_REALTIME_FAST ] FreeBSD 8.1
* [ CLOCK_REALTIME_PRECISE ] FreeBSD 8.1
2013-08-18 08:21:33 +04:00
* [ CLOCK_REALTIME_COARSE ] Linux 2.6 .32
2013-08-19 07:57:23 +04:00
* [ CLOCK_REALTIME_ALARM ] Linux 3.0
2013-08-11 06:59:30 +04:00
* [ CLOCK_MONOTONIC_FAST ] FreeBSD 8.1
* [ CLOCK_MONOTONIC_PRECISE ] FreeBSD 8.1
2013-08-18 08:21:33 +04:00
* [ CLOCK_MONOTONIC_COARSE ] Linux 2.6 .32
2016-09-21 11:46:06 +03:00
* [ CLOCK_MONOTONIC_RAW ] Linux 2.6 .28 , macOS 10.12
* [ CLOCK_MONOTONIC_RAW_APPROX ] macOS 10.12
2013-08-18 08:21:33 +04:00
* [ CLOCK_BOOTTIME ] Linux 2.6 .39
2013-08-19 07:57:23 +04:00
* [ CLOCK_BOOTTIME_ALARM ] Linux 3.0
2014-05-02 17:35:47 +04:00
* [ CLOCK_UPTIME ] FreeBSD 7.0 , OpenBSD 5.5
2013-08-11 06:59:30 +04:00
* [ CLOCK_UPTIME_FAST ] FreeBSD 8.1
2016-09-21 11:46:06 +03:00
* [ CLOCK_UPTIME_RAW ] macOS 10.12
* [ CLOCK_UPTIME_RAW_APPROX ] macOS 10.12
2013-08-11 06:59:30 +04:00
* [ CLOCK_UPTIME_PRECISE ] FreeBSD 8.1
* [ CLOCK_SECOND ] FreeBSD 8.1
2019-02-09 17:54:54 +03:00
* [ CLOCK_TAI ] Linux 3.10
2013-08-11 06:59:30 +04:00
*
2013-08-24 06:19:41 +04:00
* Note that SUS stands for Single Unix Specification .
* SUS contains POSIX and clock_gettime is defined in the POSIX part .
* SUS defines CLOCK_REALTIME mandatory but
* CLOCK_MONOTONIC , CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID are optional .
*
* Also , several symbols are accepted as + clock_id + .
2013-08-17 15:13:01 +04:00
* There are emulations for clock_gettime ( ) .
*
2013-08-12 08:48:28 +04:00
* For example , Process : : CLOCK_REALTIME is defined as
2013-08-24 05:38:34 +04:00
* + : GETTIMEOFDAY_BASED_CLOCK_REALTIME + when clock_gettime ( ) is not available .
2013-08-11 07:43:04 +04:00
*
2013-08-21 14:18:37 +04:00
* Emulations for + CLOCK_REALTIME + :
2013-08-24 05:38:34 +04:00
* [ : GETTIMEOFDAY_BASED_CLOCK_REALTIME ]
2013-08-24 06:19:41 +04:00
* Use gettimeofday ( ) defined by SUS .
2013-08-24 06:01:07 +04:00
* ( SUSv4 obsoleted it , though . )
2013-09-09 16:33:36 +04:00
* The resolution is 1 microsecond .
2013-08-24 05:38:34 +04:00
* [ : TIME_BASED_CLOCK_REALTIME ]
2013-08-24 06:01:07 +04:00
* Use time ( ) defined by ISO C .
2013-08-22 01:57:25 +04:00
* The resolution is 1 second .
2013-08-11 07:43:04 +04:00
*
2013-08-21 14:18:37 +04:00
* Emulations for + CLOCK_MONOTONIC + :
2013-08-24 06:01:07 +04:00
* [ : MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ]
* Use mach_absolute_time ( ) , available on Darwin .
* The resolution is CPU dependent .
2013-09-03 07:10:41 +04:00
* [ : TIMES_BASED_CLOCK_MONOTONIC ]
* Use the result value of times ( ) defined by POSIX .
* POSIX defines it as " times() shall return the elapsed real time, in clock ticks, since an arbitrary point in the past (for example, system start-up time) " .
* For example , GNU / Linux returns a value based on jiffies and it is monotonic .
* However , 4.4 BSD uses gettimeofday ( ) and it is not monotonic .
* ( FreeBSD uses clock_gettime ( CLOCK_MONOTONIC ) instead , though . )
* The resolution is the clock tick .
* " getconf CLK_TCK " command shows the clock ticks per second .
* ( The clock ticks per second is defined by HZ macro in older systems . )
2013-09-09 16:33:36 +04:00
* If it is 100 and clock_t is 32 bits integer type , the resolution is 10 millisecond and
2013-09-03 07:10:41 +04:00
* cannot represent over 497 days .
2013-08-17 15:13:01 +04:00
*
2013-08-21 14:18:37 +04:00
* Emulations for + CLOCK_PROCESS_CPUTIME_ID + :
2013-08-24 05:38:34 +04:00
* [ : GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID ]
2013-08-24 06:19:41 +04:00
* Use getrusage ( ) defined by SUS .
2013-08-24 06:01:07 +04:00
* getrusage ( ) is used with RUSAGE_SELF to obtain the time only for
* the calling process ( excluding the time for child processes ) .
* The result is addition of user time ( ru_utime ) and system time ( ru_stime ) .
2013-09-09 16:33:36 +04:00
* The resolution is 1 microsecond .
2013-08-24 05:38:34 +04:00
* [ : TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID ]
2013-08-21 17:33:59 +04:00
* Use times ( ) defined by POSIX .
2013-08-24 06:01:07 +04:00
* The result is addition of user time ( tms_utime ) and system time ( tms_stime ) .
* tms_cutime and tms_cstime are ignored to exclude the time for child processes .
2013-08-21 15:36:43 +04:00
* The resolution is the clock tick .
* " getconf CLK_TCK " command shows the clock ticks per second .
* ( The clock ticks per second is defined by HZ macro in older systems . )
2013-09-09 16:33:36 +04:00
* If it is 100 , the resolution is 10 millisecond .
2013-08-24 05:38:34 +04:00
* [ : CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID ]
2013-08-22 02:17:55 +04:00
* Use clock ( ) defined by ISO C .
* The resolution is 1 / CLOCKS_PER_SEC .
* CLOCKS_PER_SEC is the C - level macro defined by time . h .
2013-08-24 06:19:41 +04:00
* SUS defines CLOCKS_PER_SEC is 1000000.
2013-08-22 02:17:55 +04:00
* Non - Unix systems may define it a different value , though .
2013-09-09 16:33:36 +04:00
* If CLOCKS_PER_SEC is 1000000 as SUS , the resolution is 1 microsecond .
2013-08-24 06:19:41 +04:00
* If CLOCKS_PER_SEC is 1000000 and clock_t is 32 bits integer type , it cannot represent over 72 minutes .
2013-08-21 14:18:37 +04:00
*
2013-08-12 08:48:28 +04:00
* If the given + clock_id + is not supported , Errno : : EINVAL is raised .
2013-08-11 06:59:30 +04:00
*
2013-08-12 08:48:28 +04:00
* + unit + specifies a type of the return value .
2013-08-11 06:59:30 +04:00
*
2013-08-22 17:04:06 +04:00
* [ : float_second ] number of seconds as a float ( default )
* [ : float_millisecond ] number of milliseconds as a float
* [ : float_microsecond ] number of microseconds as a float
2013-12-16 09:04:03 +04:00
* [ : second ] number of seconds as an integer
2013-08-22 17:04:06 +04:00
* [ : millisecond ] number of milliseconds as an integer
* [ : microsecond ] number of microseconds as an integer
* [ : nanosecond ] number of nanoseconds as an integer
2013-08-11 06:59:30 +04:00
*
* The underlying function , clock_gettime ( ) , returns a number of nanoseconds .
* Float object ( IEEE 754 double ) is not enough to represent
* the return value for CLOCK_REALTIME .
2013-08-12 08:48:28 +04:00
* If the exact nanoseconds value is required , use + : nanoseconds + as the + unit + .
2013-08-11 06:59:30 +04:00
*
* The origin ( zero ) of the returned value varies .
* For example , system start up time , process start up time , the Epoch , etc .
*
* The origin in CLOCK_REALTIME is defined as the Epoch
* ( 1970 - 01 - 01 00 : 00 : 00 UTC ) .
* But some systems count leap seconds and others doesn ' t .
* So the result can be interpreted differently across systems .
* Time . now is recommended over CLOCK_REALTIME .
*/
2019-08-28 11:48:48 +03:00
static VALUE
rb_clock_gettime ( int argc , VALUE * argv , VALUE _ )
2013-08-11 06:59:30 +04:00
{
int ret ;
2013-08-23 14:44:33 +04:00
struct timetick tt ;
2013-08-23 16:46:06 +04:00
timetick_int_t numerators [ 2 ] ;
timetick_int_t denominators [ 2 ] ;
int num_numerators = 0 ;
int num_denominators = 0 ;
2013-08-23 14:44:33 +04:00
2016-04-14 07:41:47 +03:00
VALUE unit = ( rb_check_arity ( argc , 1 , 2 ) = = 2 ) ? argv [ 1 ] : Qnil ;
VALUE clk_id = argv [ 0 ] ;
2022-02-18 11:59:15 +03:00
clockid_t c ;
2013-08-11 06:59:30 +04:00
if ( SYMBOL_P ( clk_id ) ) {
2022-02-18 11:59:15 +03:00
# ifdef CLOCK_REALTIME
if ( clk_id = = RUBY_CLOCK_REALTIME ) {
c = CLOCK_REALTIME ;
goto gettime ;
}
# endif
# ifdef CLOCK_MONOTONIC
if ( clk_id = = RUBY_CLOCK_MONOTONIC ) {
c = CLOCK_MONOTONIC ;
goto gettime ;
}
# endif
# ifdef CLOCK_PROCESS_CPUTIME_ID
if ( clk_id = = RUBY_CLOCK_PROCESS_CPUTIME_ID ) {
c = CLOCK_PROCESS_CPUTIME_ID ;
goto gettime ;
}
# endif
# ifdef CLOCK_THREAD_CPUTIME_ID
if ( clk_id = = RUBY_CLOCK_THREAD_CPUTIME_ID ) {
c = CLOCK_THREAD_CPUTIME_ID ;
goto gettime ;
}
# endif
2013-08-11 06:59:30 +04:00
/*
* Non - clock_gettime clocks are provided by symbol clk_id .
2018-06-14 16:10:25 +03:00
*/
# ifdef HAVE_GETTIMEOFDAY
/*
2013-08-24 05:38:34 +04:00
* GETTIMEOFDAY_BASED_CLOCK_REALTIME is used for
2013-08-11 06:59:30 +04:00
* CLOCK_REALTIME if clock_gettime is not available .
*/
2014-11-24 06:44:24 +03:00
# define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
2013-08-24 05:38:34 +04:00
if ( clk_id = = RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ) {
2013-08-11 06:59:30 +04:00
struct timeval tv ;
ret = gettimeofday ( & tv , 0 ) ;
if ( ret ! = 0 )
rb_sys_fail ( " gettimeofday " ) ;
2013-08-23 14:44:33 +04:00
tt . giga_count = tv . tv_sec ;
2013-08-23 16:46:06 +04:00
tt . count = ( int32_t ) tv . tv_usec * 1000 ;
denominators [ num_denominators + + ] = 1000000000 ;
2013-08-11 06:59:30 +04:00
goto success ;
}
2018-06-14 16:10:25 +03:00
# endif
2013-08-11 06:59:30 +04:00
2014-11-24 06:44:24 +03:00
# define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME)
2013-08-24 05:38:34 +04:00
if ( clk_id = = RUBY_TIME_BASED_CLOCK_REALTIME ) {
2013-08-11 06:59:30 +04:00
time_t t ;
t = time ( NULL ) ;
if ( t = = ( time_t ) - 1 )
rb_sys_fail ( " time " ) ;
2013-08-23 14:44:33 +04:00
tt . giga_count = t ;
tt . count = 0 ;
2013-08-23 16:46:06 +04:00
denominators [ num_denominators + + ] = 1000000000 ;
2013-08-11 06:59:30 +04:00
goto success ;
}
2013-08-15 21:18:45 +04:00
2013-09-03 07:10:41 +04:00
# ifdef HAVE_TIMES
# define RUBY_TIMES_BASED_CLOCK_MONOTONIC \
2014-11-24 06:44:24 +03:00
ID2SYM ( id_TIMES_BASED_CLOCK_MONOTONIC )
2013-09-03 07:10:41 +04:00
if ( clk_id = = RUBY_TIMES_BASED_CLOCK_MONOTONIC ) {
struct tms buf ;
clock_t c ;
unsigned_clock_t uc ;
c = times ( & buf ) ;
if ( c = = ( clock_t ) - 1 )
rb_sys_fail ( " times " ) ;
uc = ( unsigned_clock_t ) c ;
tt . count = ( int32_t ) ( uc % 1000000000 ) ;
tt . giga_count = ( uc / 1000000000 ) ;
denominators [ num_denominators + + ] = get_clk_tck ( ) ;
goto success ;
}
# endif
2013-08-21 14:18:37 +04:00
# ifdef RUSAGE_SELF
2013-08-24 05:38:34 +04:00
# define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \
2014-11-24 06:44:24 +03:00
ID2SYM ( id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID )
2013-08-24 05:38:34 +04:00
if ( clk_id = = RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID ) {
2013-08-21 14:18:37 +04:00
struct rusage usage ;
2013-08-23 16:46:06 +04:00
int32_t usec ;
2013-08-21 14:18:37 +04:00
ret = getrusage ( RUSAGE_SELF , & usage ) ;
if ( ret ! = 0 )
rb_sys_fail ( " getrusage " ) ;
2013-08-23 14:44:33 +04:00
tt . giga_count = usage . ru_utime . tv_sec + usage . ru_stime . tv_sec ;
2013-08-23 17:25:12 +04:00
usec = ( int32_t ) ( usage . ru_utime . tv_usec + usage . ru_stime . tv_usec ) ;
2013-08-21 14:18:37 +04:00
if ( 1000000 < = usec ) {
2013-08-23 14:44:33 +04:00
tt . giga_count + + ;
2013-08-21 14:18:37 +04:00
usec - = 1000000 ;
}
2013-08-23 14:44:33 +04:00
tt . count = usec * 1000 ;
2013-08-23 16:46:06 +04:00
denominators [ num_denominators + + ] = 1000000000 ;
2013-08-21 14:18:37 +04:00
goto success ;
}
# endif
2013-08-21 15:36:43 +04:00
# ifdef HAVE_TIMES
2013-08-24 05:38:34 +04:00
# define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \
2014-11-24 06:44:24 +03:00
ID2SYM ( id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID )
2013-08-24 05:38:34 +04:00
if ( clk_id = = RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID ) {
2013-08-21 15:36:43 +04:00
struct tms buf ;
2013-08-23 14:44:33 +04:00
unsigned_clock_t utime , stime ;
2013-08-21 15:36:43 +04:00
if ( times ( & buf ) = = ( clock_t ) - 1 )
rb_sys_fail ( " times " ) ;
2013-08-23 14:44:33 +04:00
utime = ( unsigned_clock_t ) buf . tms_utime ;
stime = ( unsigned_clock_t ) buf . tms_stime ;
2013-08-23 16:46:06 +04:00
tt . count = ( int32_t ) ( ( utime % 1000000000 ) + ( stime % 1000000000 ) ) ;
2013-08-23 14:44:33 +04:00
tt . giga_count = ( utime / 1000000000 ) + ( stime / 1000000000 ) ;
if ( 1000000000 < = tt . count ) {
tt . count - = 1000000000 ;
tt . giga_count + + ;
}
2013-08-23 16:46:06 +04:00
denominators [ num_denominators + + ] = get_clk_tck ( ) ;
2013-08-21 15:36:43 +04:00
goto success ;
}
# endif
2013-08-24 05:38:34 +04:00
# define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \
2014-11-24 06:44:24 +03:00
ID2SYM ( id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID )
2013-08-24 05:38:34 +04:00
if ( clk_id = = RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID ) {
2013-08-22 02:17:55 +04:00
clock_t c ;
2013-08-22 15:19:49 +04:00
unsigned_clock_t uc ;
2013-08-22 02:17:55 +04:00
errno = 0 ;
2013-08-23 14:44:33 +04:00
c = clock ( ) ;
2013-08-22 02:17:55 +04:00
if ( c = = ( clock_t ) - 1 )
rb_sys_fail ( " clock " ) ;
2013-08-22 15:19:49 +04:00
uc = ( unsigned_clock_t ) c ;
2013-08-23 16:46:06 +04:00
tt . count = ( int32_t ) ( uc % 1000000000 ) ;
2013-08-23 14:44:33 +04:00
tt . giga_count = uc / 1000000000 ;
2013-08-23 16:46:06 +04:00
denominators [ num_denominators + + ] = CLOCKS_PER_SEC ;
2013-08-22 02:17:55 +04:00
goto success ;
}
2013-08-15 21:18:45 +04:00
# ifdef __APPLE__
2013-08-22 01:57:25 +04:00
if ( clk_id = = RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ) {
2018-06-17 02:22:42 +03:00
const mach_timebase_info_data_t * info = get_mach_timebase_info ( ) ;
2013-09-01 19:09:06 +04:00
uint64_t t = mach_absolute_time ( ) ;
2013-08-23 16:46:06 +04:00
tt . count = ( int32_t ) ( t % 1000000000 ) ;
2013-08-23 14:44:33 +04:00
tt . giga_count = t / 1000000000 ;
2013-09-01 19:09:06 +04:00
numerators [ num_numerators + + ] = info - > numer ;
denominators [ num_denominators + + ] = info - > denom ;
2013-08-23 16:46:06 +04:00
denominators [ num_denominators + + ] = 1000000000 ;
2013-08-15 21:18:45 +04:00
goto success ;
}
# endif
2013-08-11 06:59:30 +04:00
}
2022-02-18 11:59:15 +03:00
else if ( NUMERIC_CLOCKID ) {
2013-08-11 06:59:30 +04:00
# if defined(HAVE_CLOCK_GETTIME)
2013-08-23 15:53:12 +04:00
struct timespec ts ;
2013-08-11 06:59:30 +04:00
c = NUM2CLOCKID ( clk_id ) ;
2022-02-18 11:59:15 +03:00
gettime :
2013-08-11 06:59:30 +04:00
ret = clock_gettime ( c , & ts ) ;
if ( ret = = - 1 )
rb_sys_fail ( " clock_gettime " ) ;
2013-08-23 16:46:06 +04:00
tt . count = ( int32_t ) ts . tv_nsec ;
2013-08-23 14:44:33 +04:00
tt . giga_count = ts . tv_sec ;
2013-08-23 16:46:06 +04:00
denominators [ num_denominators + + ] = 1000000000 ;
2013-08-11 06:59:30 +04:00
goto success ;
# endif
}
/* EINVAL emulates clock_gettime behavior when clock_id is invalid. */
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EINVAL , 0 ) ;
2013-08-11 06:59:30 +04:00
success :
2013-08-23 16:46:06 +04:00
return make_clock_result ( & tt , numerators , num_numerators , denominators , num_denominators , unit ) ;
2013-08-11 06:59:30 +04:00
}
2013-08-31 17:21:48 +04:00
/*
* call - seq :
* Process . clock_getres ( clock_id [ , unit ] ) - > number
*
2020-04-10 15:32:32 +03:00
* Returns an estimate of the resolution of a + clock_id + using the POSIX
2020-04-10 16:44:17 +03:00
* < code > clock_getres ( ) < / code > function .
2020-04-10 15:32:32 +03:00
*
* Note the reported resolution is often inaccurate on most platforms due to
2020-04-13 19:23:39 +03:00
* underlying bugs for this function and therefore the reported resolution
2020-04-10 15:32:32 +03:00
* often differs from the actual resolution of the clock in practice .
2020-04-13 19:23:39 +03:00
* Inaccurate reported resolutions have been observed for various clocks including
* CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW when using Linux , macOS , BSD or AIX
* platforms , when using ARM processors , or when using virtualization .
2013-08-31 17:21:48 +04:00
*
* + clock_id + specifies a kind of clock .
* See the document of + Process . clock_gettime + for details .
2020-04-10 15:32:32 +03:00
* + clock_id + can be a symbol as for + Process . clock_gettime + .
2013-08-31 17:21:48 +04:00
*
* If the given + clock_id + is not supported , Errno : : EINVAL is raised .
*
2020-04-10 15:32:32 +03:00
* + unit + specifies the type of the return value .
2013-08-31 17:21:48 +04:00
* + Process . clock_getres + accepts + unit + as + Process . clock_gettime + .
2020-04-10 15:32:32 +03:00
* The default value , + : float_second + , is also the same as
2013-08-31 17:21:48 +04:00
* + Process . clock_gettime + .
*
* + Process . clock_getres + also accepts + : hertz + as + unit + .
2020-04-10 15:32:32 +03:00
* + : hertz + means the reciprocal of + : float_second + .
2013-08-31 17:21:48 +04:00
*
* + : hertz + can be used to obtain the exact value of
2020-04-10 15:32:32 +03:00
* the clock ticks per second for the times ( ) function and
* CLOCKS_PER_SEC for the clock ( ) function .
2013-08-31 17:21:48 +04:00
*
2019-03-29 03:59:34 +03:00
* < code > Process . clock_getres ( : TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID , : hertz ) < / code >
2013-08-31 17:21:48 +04:00
* returns the clock ticks per second .
*
2019-03-29 03:59:34 +03:00
* < code > Process . clock_getres ( : CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID , : hertz ) < / code >
2013-08-31 17:21:48 +04:00
* returns CLOCKS_PER_SEC .
*
* p Process . clock_getres ( Process : : CLOCK_MONOTONIC )
* # = > 1.0e-09
*
*/
2019-08-28 11:48:48 +03:00
static VALUE
rb_clock_getres ( int argc , VALUE * argv , VALUE _ )
2013-08-31 17:21:48 +04:00
{
2022-02-18 11:59:15 +03:00
int ret ;
2013-08-31 17:21:48 +04:00
struct timetick tt ;
timetick_int_t numerators [ 2 ] ;
timetick_int_t denominators [ 2 ] ;
int num_numerators = 0 ;
int num_denominators = 0 ;
2022-02-18 11:59:15 +03:00
clockid_t c ;
2013-08-31 17:21:48 +04:00
2016-04-14 07:41:47 +03:00
VALUE unit = ( rb_check_arity ( argc , 1 , 2 ) = = 2 ) ? argv [ 1 ] : Qnil ;
VALUE clk_id = argv [ 0 ] ;
2013-08-31 17:21:48 +04:00
if ( SYMBOL_P ( clk_id ) ) {
2022-02-18 11:59:15 +03:00
# ifdef CLOCK_REALTIME
if ( clk_id = = RUBY_CLOCK_REALTIME ) {
c = CLOCK_REALTIME ;
goto getres ;
}
# endif
# ifdef CLOCK_MONOTONIC
if ( clk_id = = RUBY_CLOCK_MONOTONIC ) {
c = CLOCK_MONOTONIC ;
goto getres ;
}
# endif
# ifdef CLOCK_PROCESS_CPUTIME_ID
if ( clk_id = = RUBY_CLOCK_PROCESS_CPUTIME_ID ) {
c = CLOCK_PROCESS_CPUTIME_ID ;
goto getres ;
}
# endif
# ifdef CLOCK_THREAD_CPUTIME_ID
if ( clk_id = = RUBY_CLOCK_THREAD_CPUTIME_ID ) {
c = CLOCK_THREAD_CPUTIME_ID ;
goto getres ;
}
# endif
2013-08-31 17:21:48 +04:00
# ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
if ( clk_id = = RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ) {
tt . giga_count = 0 ;
tt . count = 1000 ;
denominators [ num_denominators + + ] = 1000000000 ;
goto success ;
}
# endif
# ifdef RUBY_TIME_BASED_CLOCK_REALTIME
if ( clk_id = = RUBY_TIME_BASED_CLOCK_REALTIME ) {
tt . giga_count = 1 ;
tt . count = 0 ;
denominators [ num_denominators + + ] = 1000000000 ;
goto success ;
}
# endif
2013-09-03 07:10:41 +04:00
# ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC
if ( clk_id = = RUBY_TIMES_BASED_CLOCK_MONOTONIC ) {
tt . count = 1 ;
tt . giga_count = 0 ;
denominators [ num_denominators + + ] = get_clk_tck ( ) ;
goto success ;
}
# endif
2013-08-31 17:21:48 +04:00
# ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
if ( clk_id = = RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID ) {
tt . giga_count = 0 ;
tt . count = 1000 ;
denominators [ num_denominators + + ] = 1000000000 ;
goto success ;
}
# endif
# ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
if ( clk_id = = RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID ) {
tt . count = 1 ;
tt . giga_count = 0 ;
denominators [ num_denominators + + ] = get_clk_tck ( ) ;
goto success ;
}
# endif
# ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
if ( clk_id = = RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID ) {
tt . count = 1 ;
tt . giga_count = 0 ;
denominators [ num_denominators + + ] = CLOCKS_PER_SEC ;
goto success ;
}
# endif
# ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
2013-09-01 19:09:06 +04:00
if ( clk_id = = RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ) {
2018-06-17 02:22:42 +03:00
const mach_timebase_info_data_t * info = get_mach_timebase_info ( ) ;
2013-09-01 19:09:06 +04:00
tt . count = 1 ;
tt . giga_count = 0 ;
numerators [ num_numerators + + ] = info - > numer ;
denominators [ num_denominators + + ] = info - > denom ;
denominators [ num_denominators + + ] = 1000000000 ;
goto success ;
}
2013-08-31 17:21:48 +04:00
# endif
}
2022-02-18 11:59:15 +03:00
else if ( NUMERIC_CLOCKID ) {
2013-08-31 17:21:48 +04:00
# if defined(HAVE_CLOCK_GETRES)
struct timespec ts ;
2022-02-18 11:59:15 +03:00
c = NUM2CLOCKID ( clk_id ) ;
getres :
ret = clock_getres ( c , & ts ) ;
2013-08-31 17:21:48 +04:00
if ( ret = = - 1 )
rb_sys_fail ( " clock_getres " ) ;
tt . count = ( int32_t ) ts . tv_nsec ;
tt . giga_count = ts . tv_sec ;
denominators [ num_denominators + + ] = 1000000000 ;
goto success ;
# endif
}
/* EINVAL emulates clock_getres behavior when clock_id is invalid. */
2015-12-23 11:57:48 +03:00
rb_syserr_fail ( EINVAL , 0 ) ;
2013-08-31 17:21:48 +04:00
success :
2014-11-24 06:44:24 +03:00
if ( unit = = ID2SYM ( id_hertz ) ) {
2013-08-31 17:21:48 +04:00
return timetick2dblnum_reciprocal ( & tt , numerators , num_numerators , denominators , num_denominators ) ;
}
else {
return make_clock_result ( & tt , numerators , num_numerators , denominators , num_denominators , unit ) ;
}
}
2019-08-27 05:16:52 +03:00
static VALUE
2019-08-27 08:21:18 +03:00
get_CHILD_STATUS ( ID _x , VALUE * _y )
2019-08-27 05:16:52 +03:00
{
return rb_last_status_get ( ) ;
}
static VALUE
2019-08-27 08:21:18 +03:00
get_PROCESS_ID ( ID _x , VALUE * _y )
2019-08-27 05:16:52 +03:00
{
return get_pid ( ) ;
}
2019-08-29 04:23:14 +03:00
/*
* call - seq :
* Process . kill ( signal , pid , . . . ) - > integer
*
* Sends the given signal to the specified process id ( s ) if _pid_ is positive .
* If _pid_ is zero , _signal_ is sent to all processes whose group ID is equal
* to the group ID of the process . If _pid_ is negative , results are dependent
* on the operating system . _signal_ may be an integer signal number or
* a POSIX signal name ( either with or without a + SIG + prefix ) . If _signal_ is
* negative ( or starts with a minus sign ) , kills process groups instead of
* processes . Not all signals are available on all platforms .
* The keys and values of Signal . list are known signal names and numbers ,
* respectively .
*
* pid = fork do
* Signal . trap ( " HUP " ) { puts " Ouch! " ; exit }
* # . . . do some work . . .
* end
* # . . .
* Process . kill ( " HUP " , pid )
* Process . wait
*
* < em > produces : < / em >
*
* Ouch !
*
* If _signal_ is an integer but wrong for signal , Errno : : EINVAL or
* RangeError will be raised . Otherwise unless _signal_ is a String
* or a Symbol , and a known signal name , ArgumentError will be
* raised .
*
* Also , Errno : : ESRCH or RangeError for invalid _pid_ , Errno : : EPERM
* when failed because of no privilege , will be raised . In these
* cases , signals may have been sent to preceding processes .
*/
2019-08-28 11:48:48 +03:00
static VALUE
proc_rb_f_kill ( int c , const VALUE * v , VALUE _ )
{
return rb_f_kill ( c , v ) ;
}
1999-01-20 07:59:39 +03:00
VALUE rb_mProcess ;
ruby/ruby.h: remove unnecessary exports from C-API
Needlessly exporting can reduce performance locally and increase
binary size.
Increasing the footprint of our C-API larger is also detrimental
to our development as it encourages tighter coupling with our
internals; making it harder for us to preserve compatibility.
If some parts of the core codebase needs access to globals,
internal.h should be used instead of anything in include/ruby/*.
"Urabe, Shyouhei" <shyouhei@ruby-lang.org> wrote:
> On Thu, Jan 18, 2018 at 7:33 PM, Eric Wong <normalperson@yhbt.net> wrote:
> > shyouhei@ruby-lang.org wrote:
> >> https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61908
> >>
> >> export rb_mFConst
> >
> > Why are we exporting all these and making the public C-API bigger?
> > If anything, we should make these static. Thanks.
>
> No concrete reason, except they have already been externed in 2.5.
> These variables had lacked declarations so far, which resulted in their
> visibility to be that of extern. The commit is just confirming the status quo.
>
> I'm not against to turn them into static.
This reverts changes from r61910, r61909, r61908, r61907, and r61906.
* transcode.c (rb_eUndefinedConversionError): make static
(rb_eInvalidByteSequenceError): ditto
(rb_eConverterNotFoundError): ditto
* process.c (rb_mProcGID, rb_mProcUid, rb_mProcID_Syscall): ditto
* file.c (rb_mFConst): ditto
* error.c (rb_mWarning, rb_cWarningBuffer): ditto
* enumerator.c (rb_cLazy): ditto
[Misc #14381]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-25 00:07:14 +03:00
static VALUE rb_mProcUID ;
static VALUE rb_mProcGID ;
static VALUE rb_mProcID_Syscall ;
1998-01-16 15:13:05 +03:00
2004-01-02 09:01:12 +03:00
/*
2019-03-28 06:33:35 +03:00
* The Process module is a collection of methods used to
2004-01-02 09:01:12 +03:00
* manipulate processes .
*/
1998-01-16 15:13:05 +03:00
void
2014-11-25 06:14:45 +03:00
InitVM_process ( void )
1998-01-16 15:13:05 +03:00
{
2019-08-27 08:21:18 +03:00
rb_define_virtual_variable ( " $? " , get_CHILD_STATUS , 0 ) ;
rb_define_virtual_variable ( " $$ " , get_PROCESS_ID , 0 ) ;
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
rb_gvar_ractor_local ( " $$ " ) ;
rb_gvar_ractor_local ( " $? " ) ;
2019-08-28 12:19:11 +03:00
rb_define_global_function ( " exec " , f_exec , - 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_global_function ( " fork " , rb_f_fork , 0 ) ;
1999-08-13 09:45:20 +04:00
rb_define_global_function ( " exit! " , rb_f_exit_bang , - 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_global_function ( " system " , rb_f_system , - 1 ) ;
2004-02-16 09:45:32 +03:00
rb_define_global_function ( " spawn " , rb_f_spawn , - 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_global_function ( " sleep " , rb_f_sleep , - 1 ) ;
2019-08-28 12:19:11 +03:00
rb_define_global_function ( " exit " , f_exit , - 1 ) ;
rb_define_global_function ( " abort " , f_abort , - 1 ) ;
1998-01-16 15:13:05 +03:00
1999-01-20 07:59:39 +03:00
rb_mProcess = rb_define_module ( " Process " ) ;
1998-01-16 15:13:05 +03:00
# ifdef WNOHANG
2011-05-13 00:39:11 +04:00
/* see Process.wait */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " WNOHANG " , INT2FIX ( WNOHANG ) ) ;
1998-01-16 15:13:05 +03:00
# else
2011-05-13 00:39:11 +04:00
/* see Process.wait */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " WNOHANG " , INT2FIX ( 0 ) ) ;
1998-01-16 15:13:05 +03:00
# endif
# ifdef WUNTRACED
2011-05-13 00:39:11 +04:00
/* see Process.wait */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " WUNTRACED " , INT2FIX ( WUNTRACED ) ) ;
1998-01-16 15:13:05 +03:00
# else
2011-05-13 00:39:11 +04:00
/* see Process.wait */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " WUNTRACED " , INT2FIX ( 0 ) ) ;
1998-01-16 15:13:05 +03:00
# endif
2019-08-28 12:19:11 +03:00
rb_define_singleton_method ( rb_mProcess , " exec " , f_exec , - 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_singleton_method ( rb_mProcess , " fork " , rb_f_fork , 0 ) ;
2004-02-16 09:45:32 +03:00
rb_define_singleton_method ( rb_mProcess , " spawn " , rb_f_spawn , - 1 ) ;
1999-08-13 09:45:20 +04:00
rb_define_singleton_method ( rb_mProcess , " exit! " , rb_f_exit_bang , - 1 ) ;
2019-08-28 12:19:11 +03:00
rb_define_singleton_method ( rb_mProcess , " exit " , f_exit , - 1 ) ;
rb_define_singleton_method ( rb_mProcess , " abort " , f_abort , - 1 ) ;
2017-12-12 12:00:17 +03:00
rb_define_singleton_method ( rb_mProcess , " last_status " , proc_s_last_status , 0 ) ;
2021-10-25 14:47:19 +03:00
rb_define_singleton_method ( rb_mProcess , " _fork " , rb_proc__fork , 0 ) ;
2001-10-09 13:42:47 +04:00
2019-08-28 11:48:48 +03:00
rb_define_module_function ( rb_mProcess , " kill " , proc_rb_f_kill , - 1 ) ;
rb_define_module_function ( rb_mProcess , " wait " , proc_m_wait , - 1 ) ;
2001-08-06 07:05:23 +04:00
rb_define_module_function ( rb_mProcess , " wait2 " , proc_wait2 , - 1 ) ;
2019-08-28 11:48:48 +03:00
rb_define_module_function ( rb_mProcess , " waitpid " , proc_m_wait , - 1 ) ;
2001-08-06 07:05:23 +04:00
rb_define_module_function ( rb_mProcess , " waitpid2 " , proc_wait2 , - 1 ) ;
2001-02-15 09:01:00 +03:00
rb_define_module_function ( rb_mProcess , " waitall " , proc_waitall , 0 ) ;
2003-03-07 08:59:42 +03:00
rb_define_module_function ( rb_mProcess , " detach " , proc_detach , 1 ) ;
1998-01-16 15:13:05 +03:00
2018-02-23 05:16:42 +03:00
/* :nodoc: */
2014-09-12 23:42:01 +04:00
rb_cWaiter = rb_define_class_under ( rb_mProcess , " Waiter " , rb_cThread ) ;
rb_undef_alloc_func ( rb_cWaiter ) ;
rb_undef_method ( CLASS_OF ( rb_cWaiter ) , " new " ) ;
rb_define_method ( rb_cWaiter , " pid " , detach_process_pid , 0 ) ;
2008-04-26 12:31:13 +04:00
rb_cProcessStatus = rb_define_class_under ( rb_mProcess , " Status " , rb_cObject ) ;
2020-12-07 23:29:09 +03:00
rb_define_alloc_func ( rb_cProcessStatus , rb_process_status_allocate ) ;
2008-04-26 12:31:13 +04:00
rb_undef_method ( CLASS_OF ( rb_cProcessStatus ) , " new " ) ;
2020-12-16 06:31:40 +03:00
rb_marshal_define_compat ( rb_cProcessStatus , rb_cObject ,
process_status_dump , process_status_load ) ;
2001-02-15 09:01:00 +03:00
2020-12-07 23:29:09 +03:00
rb_define_singleton_method ( rb_cProcessStatus , " wait " , rb_process_status_waitv , - 1 ) ;
2008-04-26 12:31:13 +04:00
rb_define_method ( rb_cProcessStatus , " == " , pst_equal , 1 ) ;
rb_define_method ( rb_cProcessStatus , " & " , pst_bitand , 1 ) ;
rb_define_method ( rb_cProcessStatus , " >> " , pst_rshift , 1 ) ;
rb_define_method ( rb_cProcessStatus , " to_i " , pst_to_i , 0 ) ;
rb_define_method ( rb_cProcessStatus , " to_s " , pst_to_s , 0 ) ;
rb_define_method ( rb_cProcessStatus , " inspect " , pst_inspect , 0 ) ;
2001-02-15 09:01:00 +03:00
2020-12-24 13:47:35 +03:00
rb_define_method ( rb_cProcessStatus , " pid " , pst_pid_m , 0 ) ;
2002-12-10 09:23:44 +03:00
2008-04-26 12:31:13 +04:00
rb_define_method ( rb_cProcessStatus , " stopped? " , pst_wifstopped , 0 ) ;
rb_define_method ( rb_cProcessStatus , " stopsig " , pst_wstopsig , 0 ) ;
rb_define_method ( rb_cProcessStatus , " signaled? " , pst_wifsignaled , 0 ) ;
rb_define_method ( rb_cProcessStatus , " termsig " , pst_wtermsig , 0 ) ;
rb_define_method ( rb_cProcessStatus , " exited? " , pst_wifexited , 0 ) ;
rb_define_method ( rb_cProcessStatus , " exitstatus " , pst_wexitstatus , 0 ) ;
rb_define_method ( rb_cProcessStatus , " success? " , pst_success_p , 0 ) ;
rb_define_method ( rb_cProcessStatus , " coredump? " , pst_wcoredump , 0 ) ;
2001-02-15 09:01:00 +03:00
2019-08-28 11:48:48 +03:00
rb_define_module_function ( rb_mProcess , " pid " , proc_get_pid , 0 ) ;
rb_define_module_function ( rb_mProcess , " ppid " , proc_get_ppid , 0 ) ;
1998-01-16 15:13:05 +03:00
2001-08-06 07:05:23 +04:00
rb_define_module_function ( rb_mProcess , " getpgrp " , proc_getpgrp , 0 ) ;
rb_define_module_function ( rb_mProcess , " setpgrp " , proc_setpgrp , 0 ) ;
1999-01-20 07:59:39 +03:00
rb_define_module_function ( rb_mProcess , " getpgid " , proc_getpgid , 1 ) ;
rb_define_module_function ( rb_mProcess , " setpgid " , proc_setpgid , 2 ) ;
1998-01-16 15:13:05 +03:00
2012-11-24 06:51:24 +04:00
rb_define_module_function ( rb_mProcess , " getsid " , proc_getsid , - 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_module_function ( rb_mProcess , " setsid " , proc_setsid , 0 ) ;
rb_define_module_function ( rb_mProcess , " getpriority " , proc_getpriority , 2 ) ;
rb_define_module_function ( rb_mProcess , " setpriority " , proc_setpriority , 3 ) ;
1998-01-16 15:13:05 +03:00
1999-01-20 07:59:39 +03:00
# ifdef HAVE_GETPRIORITY
2011-05-13 00:39:11 +04:00
/* see Process.setpriority */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " PRIO_PROCESS " , INT2FIX ( PRIO_PROCESS ) ) ;
2011-05-13 00:39:11 +04:00
/* see Process.setpriority */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " PRIO_PGRP " , INT2FIX ( PRIO_PGRP ) ) ;
2011-05-13 00:39:11 +04:00
/* see Process.setpriority */
1999-01-20 07:59:39 +03:00
rb_define_const ( rb_mProcess , " PRIO_USER " , INT2FIX ( PRIO_USER ) ) ;
1998-01-16 15:13:05 +03:00
# endif
2004-11-14 13:06:16 +03:00
rb_define_module_function ( rb_mProcess , " getrlimit " , proc_getrlimit , 1 ) ;
2005-09-24 20:36:11 +04:00
rb_define_module_function ( rb_mProcess , " setrlimit " , proc_setrlimit , - 1 ) ;
2011-03-07 11:44:45 +03:00
# if defined(RLIM2NUM) && defined(RLIM_INFINITY)
2008-02-25 07:58:47 +03:00
{
2008-06-29 21:13:37 +04:00
VALUE inf = RLIM2NUM ( RLIM_INFINITY ) ;
2004-11-14 13:06:16 +03:00
# ifdef RLIM_SAVED_MAX
2009-03-23 15:53:52 +03:00
{
VALUE v = RLIM_INFINITY = = RLIM_SAVED_MAX ? inf : RLIM2NUM ( RLIM_SAVED_MAX ) ;
2011-05-13 00:39:11 +04:00
/* see Process.setrlimit */
2009-03-23 15:53:52 +03:00
rb_define_const ( rb_mProcess , " RLIM_SAVED_MAX " , v ) ;
}
2004-11-14 13:06:16 +03:00
# endif
2011-05-13 00:39:11 +04:00
/* see Process.setrlimit */
2008-06-29 21:13:37 +04:00
rb_define_const ( rb_mProcess , " RLIM_INFINITY " , inf ) ;
2004-11-14 13:06:16 +03:00
# ifdef RLIM_SAVED_CUR
2009-03-23 15:53:52 +03:00
{
VALUE v = RLIM_INFINITY = = RLIM_SAVED_CUR ? inf : RLIM2NUM ( RLIM_SAVED_CUR ) ;
2011-05-13 00:39:11 +04:00
/* see Process.setrlimit */
2009-03-23 15:53:52 +03:00
rb_define_const ( rb_mProcess , " RLIM_SAVED_CUR " , v ) ;
}
2004-11-14 13:06:16 +03:00
# endif
2008-02-25 07:58:47 +03:00
}
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_AS
2011-05-13 00:39:11 +04:00
/* Maximum size of the process's virtual memory (address space) in bytes.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_AS " , INT2FIX ( RLIMIT_AS ) ) ;
# endif
2004-11-14 13:06:16 +03:00
# ifdef RLIMIT_CORE
2011-05-13 00:39:11 +04:00
/* Maximum size of the core file.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_CORE " , INT2FIX ( RLIMIT_CORE ) ) ;
# endif
# ifdef RLIMIT_CPU
2011-05-13 00:39:11 +04:00
/* CPU time limit in seconds.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_CPU " , INT2FIX ( RLIMIT_CPU ) ) ;
# endif
# ifdef RLIMIT_DATA
2011-05-13 00:39:11 +04:00
/* Maximum size of the process's data segment.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_DATA " , INT2FIX ( RLIMIT_DATA ) ) ;
# endif
# ifdef RLIMIT_FSIZE
2011-05-13 00:39:11 +04:00
/* Maximum size of files that the process may create.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_FSIZE " , INT2FIX ( RLIMIT_FSIZE ) ) ;
# endif
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_MEMLOCK
2011-05-13 00:39:11 +04:00
/* Maximum number of bytes of memory that may be locked into RAM.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_MEMLOCK " , INT2FIX ( RLIMIT_MEMLOCK ) ) ;
2004-11-14 13:06:16 +03:00
# endif
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_MSGQUEUE
2011-05-13 00:39:11 +04:00
/* Specifies the limit on the number of bytes that can be allocated
* for POSIX message queues for the real user ID of the calling process .
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_MSGQUEUE " , INT2FIX ( RLIMIT_MSGQUEUE ) ) ;
2004-11-14 13:06:16 +03:00
# endif
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_NICE
2011-05-13 00:39:11 +04:00
/* Specifies a ceiling to which the process's nice value can be raised.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_NICE " , INT2FIX ( RLIMIT_NICE ) ) ;
2004-11-14 13:06:16 +03:00
# endif
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_NOFILE
2011-05-13 00:39:11 +04:00
/* Specifies a value one greater than the maximum file descriptor
* number that can be opened by this process .
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_NOFILE " , INT2FIX ( RLIMIT_NOFILE ) ) ;
2004-11-14 13:06:16 +03:00
# endif
# ifdef RLIMIT_NPROC
2011-05-13 00:39:11 +04:00
/* The maximum number of processes that can be created for the
* real user ID of the calling process .
*
* see the system getrlimit ( 2 ) manual for details .
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_NPROC " , INT2FIX ( RLIMIT_NPROC ) ) ;
# endif
# ifdef RLIMIT_RSS
2011-05-13 00:39:11 +04:00
/* Specifies the limit (in pages) of the process's resident set.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_RSS " , INT2FIX ( RLIMIT_RSS ) ) ;
# endif
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_RTPRIO
2011-05-13 00:39:11 +04:00
/* Specifies a ceiling on the real-time priority that may be set for this process.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_RTPRIO " , INT2FIX ( RLIMIT_RTPRIO ) ) ;
# endif
# ifdef RLIMIT_RTTIME
2011-05-13 00:39:11 +04:00
/* Specifies limit on CPU time this process scheduled under a real-time
* scheduling policy can consume .
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_RTTIME " , INT2FIX ( RLIMIT_RTTIME ) ) ;
# endif
2004-11-14 13:06:16 +03:00
# ifdef RLIMIT_SBSIZE
2011-05-13 00:39:11 +04:00
/* Maximum size of the socket buffer.
*/
2004-11-14 13:06:16 +03:00
rb_define_const ( rb_mProcess , " RLIMIT_SBSIZE " , INT2FIX ( RLIMIT_SBSIZE ) ) ;
# endif
2010-09-12 03:38:44 +04:00
# ifdef RLIMIT_SIGPENDING
2011-05-13 00:39:11 +04:00
/* Specifies a limit on the number of signals that may be queued for
* the real user ID of the calling process .
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_SIGPENDING " , INT2FIX ( RLIMIT_SIGPENDING ) ) ;
# endif
# ifdef RLIMIT_STACK
2011-05-13 00:39:11 +04:00
/* Maximum size of the stack, in bytes.
*
* see the system getrlimit ( 2 ) manual for details .
*/
2010-09-12 03:38:44 +04:00
rb_define_const ( rb_mProcess , " RLIMIT_STACK " , INT2FIX ( RLIMIT_STACK ) ) ;
# endif
2004-11-14 13:06:16 +03:00
# endif
1999-01-20 07:59:39 +03:00
rb_define_module_function ( rb_mProcess , " uid " , proc_getuid , 0 ) ;
rb_define_module_function ( rb_mProcess , " uid= " , proc_setuid , 1 ) ;
rb_define_module_function ( rb_mProcess , " gid " , proc_getgid , 0 ) ;
rb_define_module_function ( rb_mProcess , " gid= " , proc_setgid , 1 ) ;
rb_define_module_function ( rb_mProcess , " euid " , proc_geteuid , 0 ) ;
2009-04-18 20:41:16 +04:00
rb_define_module_function ( rb_mProcess , " euid= " , proc_seteuid_m , 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_module_function ( rb_mProcess , " egid " , proc_getegid , 0 ) ;
2009-04-18 20:41:16 +04:00
rb_define_module_function ( rb_mProcess , " egid= " , proc_setegid_m , 1 ) ;
2003-07-23 06:39:46 +04:00
rb_define_module_function ( rb_mProcess , " initgroups " , proc_initgroups , 2 ) ;
2003-06-07 19:34:31 +04:00
rb_define_module_function ( rb_mProcess , " groups " , proc_getgroups , 0 ) ;
rb_define_module_function ( rb_mProcess , " groups= " , proc_setgroups , 1 ) ;
rb_define_module_function ( rb_mProcess , " maxgroups " , proc_getmaxgroups , 0 ) ;
rb_define_module_function ( rb_mProcess , " maxgroups= " , proc_setmaxgroups , 1 ) ;
2001-02-16 10:53:21 +03:00
2004-08-17 13:02:40 +04:00
rb_define_module_function ( rb_mProcess , " daemon " , proc_daemon , - 1 ) ;
2001-02-16 10:53:21 +03:00
rb_define_module_function ( rb_mProcess , " times " , rb_proc_times , 0 ) ;
2022-02-18 11:59:15 +03:00
# if defined(RUBY_CLOCK_REALTIME)
2013-08-24 05:38:34 +04:00
# elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
2022-02-18 11:59:15 +03:00
# define RUBY_CLOCK_REALTIME RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
# elif defined(RUBY_TIME_BASED_CLOCK_REALTIME)
# define RUBY_CLOCK_REALTIME RUBY_TIME_BASED_CLOCK_REALTIME
2013-08-11 06:59:30 +04:00
# endif
2022-02-18 11:59:15 +03:00
# if defined(CLOCK_REALTIME) && defined(CLOCKID2NUM)
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2022-02-18 11:59:15 +03:00
rb_define_const ( rb_mProcess , " CLOCK_REALTIME " , CLOCKID2NUM ( CLOCK_REALTIME ) ) ;
# elif defined(RUBY_CLOCK_REALTIME)
rb_define_const ( rb_mProcess , " CLOCK_REALTIME " , RUBY_CLOCK_REALTIME ) ;
# endif
# if defined(RUBY_CLOCK_MONOTONIC)
2013-08-22 01:57:25 +04:00
# elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
2022-02-18 11:59:15 +03:00
# define RUBY_CLOCK_MONOTONIC RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
2013-08-11 06:59:30 +04:00
# endif
2022-02-18 11:59:15 +03:00
# if defined(CLOCK_MONOTONIC) && defined(CLOCKID2NUM)
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2022-02-18 11:59:15 +03:00
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC " , CLOCKID2NUM ( CLOCK_MONOTONIC ) ) ;
# elif defined(RUBY_CLOCK_MONOTONIC)
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC " , RUBY_CLOCK_MONOTONIC ) ;
# endif
# if defined(RUBY_CLOCK_PROCESS_CPUTIME_ID)
2013-08-24 05:38:34 +04:00
# elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
2022-02-18 11:59:15 +03:00
# define RUBY_CLOCK_PROCESS_CPUTIME_ID RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
# endif
# if defined(CLOCK_PROCESS_CPUTIME_ID) && defined(CLOCKID2NUM)
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2022-02-18 11:59:15 +03:00
rb_define_const ( rb_mProcess , " CLOCK_PROCESS_CPUTIME_ID " , CLOCKID2NUM ( CLOCK_PROCESS_CPUTIME_ID ) ) ;
# elif defined(RUBY_CLOCK_PROCESS_CPUTIME_ID)
rb_define_const ( rb_mProcess , " CLOCK_PROCESS_CPUTIME_ID " , RUBY_CLOCK_PROCESS_CPUTIME_ID ) ;
2013-08-11 06:59:30 +04:00
# endif
2022-02-18 11:59:15 +03:00
# if defined(CLOCK_THREAD_CPUTIME_ID) && defined(CLOCKID2NUM)
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_THREAD_CPUTIME_ID " , CLOCKID2NUM ( CLOCK_THREAD_CPUTIME_ID ) ) ;
2022-02-18 11:59:15 +03:00
# elif defined(RUBY_CLOCK_THREAD_CPUTIME_ID)
rb_define_const ( rb_mProcess , " CLOCK_THREAD_CPUTIME_ID " , RUBY_CLOCK_THREAD_CPUTIME_ID ) ;
2013-08-11 06:59:30 +04:00
# endif
2022-02-18 11:59:15 +03:00
# ifdef CLOCKID2NUM
2013-08-11 06:59:30 +04:00
# ifdef CLOCK_VIRTUAL
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_VIRTUAL " , CLOCKID2NUM ( CLOCK_VIRTUAL ) ) ;
# endif
# ifdef CLOCK_PROF
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_PROF " , CLOCKID2NUM ( CLOCK_PROF ) ) ;
# endif
# ifdef CLOCK_REALTIME_FAST
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_REALTIME_FAST " , CLOCKID2NUM ( CLOCK_REALTIME_FAST ) ) ;
# endif
# ifdef CLOCK_REALTIME_PRECISE
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_REALTIME_PRECISE " , CLOCKID2NUM ( CLOCK_REALTIME_PRECISE ) ) ;
# endif
2013-08-18 08:21:33 +04:00
# ifdef CLOCK_REALTIME_COARSE
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-18 08:21:33 +04:00
rb_define_const ( rb_mProcess , " CLOCK_REALTIME_COARSE " , CLOCKID2NUM ( CLOCK_REALTIME_COARSE ) ) ;
# endif
2013-08-19 07:57:23 +04:00
# ifdef CLOCK_REALTIME_ALARM
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-19 07:57:23 +04:00
rb_define_const ( rb_mProcess , " CLOCK_REALTIME_ALARM " , CLOCKID2NUM ( CLOCK_REALTIME_ALARM ) ) ;
# endif
2013-08-11 06:59:30 +04:00
# ifdef CLOCK_MONOTONIC_FAST
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC_FAST " , CLOCKID2NUM ( CLOCK_MONOTONIC_FAST ) ) ;
# endif
# ifdef CLOCK_MONOTONIC_PRECISE
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC_PRECISE " , CLOCKID2NUM ( CLOCK_MONOTONIC_PRECISE ) ) ;
# endif
# ifdef CLOCK_MONOTONIC_RAW
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC_RAW " , CLOCKID2NUM ( CLOCK_MONOTONIC_RAW ) ) ;
# endif
2016-09-21 11:46:06 +03:00
# ifdef CLOCK_MONOTONIC_RAW_APPROX
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2016-09-21 11:46:06 +03:00
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC_RAW_APPROX " , CLOCKID2NUM ( CLOCK_MONOTONIC_RAW_APPROX ) ) ;
# endif
2013-08-18 08:21:33 +04:00
# ifdef CLOCK_MONOTONIC_COARSE
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-18 08:21:33 +04:00
rb_define_const ( rb_mProcess , " CLOCK_MONOTONIC_COARSE " , CLOCKID2NUM ( CLOCK_MONOTONIC_COARSE ) ) ;
# endif
# ifdef CLOCK_BOOTTIME
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-18 08:21:33 +04:00
rb_define_const ( rb_mProcess , " CLOCK_BOOTTIME " , CLOCKID2NUM ( CLOCK_BOOTTIME ) ) ;
# endif
2013-08-19 07:57:23 +04:00
# ifdef CLOCK_BOOTTIME_ALARM
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-19 07:57:23 +04:00
rb_define_const ( rb_mProcess , " CLOCK_BOOTTIME_ALARM " , CLOCKID2NUM ( CLOCK_BOOTTIME_ALARM ) ) ;
# endif
2013-08-11 06:59:30 +04:00
# ifdef CLOCK_UPTIME
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_UPTIME " , CLOCKID2NUM ( CLOCK_UPTIME ) ) ;
# endif
# ifdef CLOCK_UPTIME_FAST
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_UPTIME_FAST " , CLOCKID2NUM ( CLOCK_UPTIME_FAST ) ) ;
# endif
# ifdef CLOCK_UPTIME_PRECISE
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_UPTIME_PRECISE " , CLOCKID2NUM ( CLOCK_UPTIME_PRECISE ) ) ;
# endif
2016-09-21 11:46:06 +03:00
# ifdef CLOCK_UPTIME_RAW
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2016-09-21 11:46:06 +03:00
rb_define_const ( rb_mProcess , " CLOCK_UPTIME_RAW " , CLOCKID2NUM ( CLOCK_UPTIME_RAW ) ) ;
# endif
# ifdef CLOCK_UPTIME_RAW_APPROX
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2016-09-21 11:46:06 +03:00
rb_define_const ( rb_mProcess , " CLOCK_UPTIME_RAW_APPROX " , CLOCKID2NUM ( CLOCK_UPTIME_RAW_APPROX ) ) ;
# endif
2013-08-11 06:59:30 +04:00
# ifdef CLOCK_SECOND
2017-03-29 12:31:13 +03:00
/* see Process.clock_gettime */
2013-08-11 06:59:30 +04:00
rb_define_const ( rb_mProcess , " CLOCK_SECOND " , CLOCKID2NUM ( CLOCK_SECOND ) ) ;
2019-02-09 17:54:54 +03:00
# endif
# ifdef CLOCK_TAI
/* see Process.clock_gettime */
rb_define_const ( rb_mProcess , " CLOCK_TAI " , CLOCKID2NUM ( CLOCK_TAI ) ) ;
2022-02-18 11:59:15 +03:00
# endif
2013-08-11 06:59:30 +04:00
# endif
rb_define_module_function ( rb_mProcess , " clock_gettime " , rb_clock_gettime , - 1 ) ;
2013-08-31 17:21:48 +04:00
rb_define_module_function ( rb_mProcess , " clock_getres " , rb_clock_getres , - 1 ) ;
2013-08-11 06:59:30 +04:00
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
# if defined(HAVE_TIMES) || defined(_WIN32)
2018-02-23 05:18:52 +03:00
/* Placeholder for rusage */
2013-10-27 05:38:20 +04:00
rb_cProcessTms = rb_struct_define_under ( rb_mProcess , " Tms " , " utime " , " stime " , " cutime " , " cstime " , NULL ) ;
2001-02-16 10:53:21 +03:00
# endif
2003-07-23 06:39:46 +04:00
SAVED_USER_ID = geteuid ( ) ;
SAVED_GROUP_ID = getegid ( ) ;
rb_mProcUID = rb_define_module_under ( rb_mProcess , " UID " ) ;
rb_mProcGID = rb_define_module_under ( rb_mProcess , " GID " ) ;
rb_define_module_function ( rb_mProcUID , " rid " , proc_getuid , 0 ) ;
rb_define_module_function ( rb_mProcGID , " rid " , proc_getgid , 0 ) ;
rb_define_module_function ( rb_mProcUID , " eid " , proc_geteuid , 0 ) ;
rb_define_module_function ( rb_mProcGID , " eid " , proc_getegid , 0 ) ;
2004-11-18 06:45:23 +03:00
rb_define_module_function ( rb_mProcUID , " change_privilege " , p_uid_change_privilege , 1 ) ;
rb_define_module_function ( rb_mProcGID , " change_privilege " , p_gid_change_privilege , 1 ) ;
rb_define_module_function ( rb_mProcUID , " grant_privilege " , p_uid_grant_privilege , 1 ) ;
rb_define_module_function ( rb_mProcGID , " grant_privilege " , p_gid_grant_privilege , 1 ) ;
2007-06-12 06:32:28 +04:00
rb_define_alias ( rb_singleton_class ( rb_mProcUID ) , " eid= " , " grant_privilege " ) ;
rb_define_alias ( rb_singleton_class ( rb_mProcGID ) , " eid= " , " grant_privilege " ) ;
2003-07-23 06:39:46 +04:00
rb_define_module_function ( rb_mProcUID , " re_exchange " , p_uid_exchange , 0 ) ;
rb_define_module_function ( rb_mProcGID , " re_exchange " , p_gid_exchange , 0 ) ;
2004-11-18 06:45:23 +03:00
rb_define_module_function ( rb_mProcUID , " re_exchangeable? " , p_uid_exchangeable , 0 ) ;
rb_define_module_function ( rb_mProcGID , " re_exchangeable? " , p_gid_exchangeable , 0 ) ;
rb_define_module_function ( rb_mProcUID , " sid_available? " , p_uid_have_saved_id , 0 ) ;
rb_define_module_function ( rb_mProcGID , " sid_available? " , p_gid_have_saved_id , 0 ) ;
2003-07-23 06:39:46 +04:00
rb_define_module_function ( rb_mProcUID , " switch " , p_uid_switch , 0 ) ;
2003-07-24 22:33:50 +04:00
rb_define_module_function ( rb_mProcGID , " switch " , p_gid_switch , 0 ) ;
2012-03-28 11:40:02 +04:00
# ifdef p_uid_from_name
rb_define_module_function ( rb_mProcUID , " from_name " , p_uid_from_name , 1 ) ;
# endif
# ifdef p_gid_from_name
rb_define_module_function ( rb_mProcGID , " from_name " , p_gid_from_name , 1 ) ;
# endif
2003-07-23 06:39:46 +04:00
rb_mProcID_Syscall = rb_define_module_under ( rb_mProcess , " Sys " ) ;
rb_define_module_function ( rb_mProcID_Syscall , " getuid " , proc_getuid , 0 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " geteuid " , proc_geteuid , 0 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " getgid " , proc_getgid , 0 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " getegid " , proc_getegid , 0 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setuid " , p_sys_setuid , 1 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setgid " , p_sys_setgid , 1 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setruid " , p_sys_setruid , 1 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setrgid " , p_sys_setrgid , 1 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " seteuid " , p_sys_seteuid , 1 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setegid " , p_sys_setegid , 1 ) ;
2004-11-18 06:45:23 +03:00
rb_define_module_function ( rb_mProcID_Syscall , " setreuid " , p_sys_setreuid , 2 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setregid " , p_sys_setregid , 2 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setresuid " , p_sys_setresuid , 3 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " setresgid " , p_sys_setresgid , 3 ) ;
rb_define_module_function ( rb_mProcID_Syscall , " issetugid " , p_sys_issetugid , 0 ) ;
2014-11-25 06:14:45 +03:00
}
2014-11-24 06:44:24 +03:00
2014-11-25 06:14:45 +03:00
void
Init_process ( void )
{
2022-02-18 18:10:50 +03:00
# define define_id(name) id_##name = rb_intern_const(#name)
define_id ( in ) ;
define_id ( out ) ;
define_id ( err ) ;
define_id ( pid ) ;
define_id ( uid ) ;
define_id ( gid ) ;
define_id ( close ) ;
define_id ( child ) ;
2014-11-24 06:44:24 +03:00
# ifdef HAVE_SETPGID
2022-02-18 18:10:50 +03:00
define_id ( pgroup ) ;
2014-11-24 06:44:24 +03:00
# endif
# ifdef _WIN32
2022-02-18 18:10:50 +03:00
define_id ( new_pgroup ) ;
# endif
define_id ( unsetenv_others ) ;
define_id ( chdir ) ;
define_id ( umask ) ;
define_id ( close_others ) ;
define_id ( nanosecond ) ;
define_id ( microsecond ) ;
define_id ( millisecond ) ;
define_id ( second ) ;
define_id ( float_microsecond ) ;
define_id ( float_millisecond ) ;
define_id ( float_second ) ;
define_id ( GETTIMEOFDAY_BASED_CLOCK_REALTIME ) ;
define_id ( TIME_BASED_CLOCK_REALTIME ) ;
2022-02-18 11:59:15 +03:00
# ifdef CLOCK_REALTIME
define_id ( CLOCK_REALTIME ) ;
# endif
# ifdef CLOCK_MONOTONIC
define_id ( CLOCK_MONOTONIC ) ;
# endif
# ifdef CLOCK_PROCESS_CPUTIME_ID
define_id ( CLOCK_PROCESS_CPUTIME_ID ) ;
# endif
# ifdef CLOCK_THREAD_CPUTIME_ID
define_id ( CLOCK_THREAD_CPUTIME_ID ) ;
# endif
2014-11-24 06:44:24 +03:00
# ifdef HAVE_TIMES
2022-02-18 18:10:50 +03:00
define_id ( TIMES_BASED_CLOCK_MONOTONIC ) ;
define_id ( TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID ) ;
2014-11-24 06:44:24 +03:00
# endif
# ifdef RUSAGE_SELF
2022-02-18 18:10:50 +03:00
define_id ( GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID ) ;
2014-11-24 06:44:24 +03:00
# endif
2022-02-18 18:10:50 +03:00
define_id ( CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID ) ;
2014-11-24 06:44:24 +03:00
# ifdef __APPLE__
2022-02-18 18:10:50 +03:00
define_id ( MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ) ;
2014-11-24 06:44:24 +03:00
# endif
2022-02-18 18:10:50 +03:00
define_id ( hertz ) ;
2014-11-25 06:14:45 +03:00
InitVM ( process ) ;
1998-01-16 15:13:05 +03:00
}