Ruby
2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
|
Go to the documentation of this file. 1 #include "ruby/config.h"
3 #include RUBY_EXTCONF_H
15 #ifdef HAVE_SYS_IOCTL_H
16 #include <sys/ioctl.h>
27 #if defined(HAVE_SYS_PARAM_H)
29 # include <sys/param.h>
31 #ifdef HAVE_SYS_WAIT_H
34 #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
43 #ifdef HAVE_SYS_STROPTS_H
44 #include <sys/stropts.h>
55 # define seteuid(e) setreuid(-1, (e))
57 # ifdef HAVE_SETRESUID
58 # define seteuid(e) setresuid(-1, (e), -1)
65 static VALUE eChildExited;
71 echild_status(
VALUE self)
81 static void getDevice(
int*,
int*,
char [
DEVICELEN],
int);
91 chfunc(
void *data,
char *errbuf,
size_t errbuf_len)
97 #define ERROR_EXIT(str) do { \
98 strlcpy(errbuf, (str), errbuf_len); \
119 if (
ioctl(
i, TIOCNOTTY, (
char *)0))
130 #if defined(TIOCSCTTY)
147 #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
167 const char *shellname =
"/bin/sh";
173 #if defined HAVE_PWD_H
174 const char *username =
getenv(
"USER");
175 struct passwd *pwent = getpwnam(username ? username :
getlogin());
176 if (pwent && pwent->pw_shell)
177 shellname = pwent->pw_shell;
189 getDevice(&master, &slave, SlaveName, 0);
216 #if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME)
218 no_mesg(
char *slavedevice,
int nomesg)
221 return chmod(slavedevice, 0600);
227 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
229 ioctl_I_PUSH(
int fd,
const char *
const name)
243 get_device_once(
int *master,
int *slave,
char SlaveName[
DEVICELEN],
int nomesg,
int fail)
245 #if defined(HAVE_POSIX_OPENPT)
247 int masterfd = -1, slavefd = -1;
250 #if defined(__sun) || defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 902000)
259 int flags = O_RDWR|O_NOCTTY;
260 # if defined(O_CLOEXEC)
273 if (no_mesg(slavedevice, nomesg) == -1)
goto error;
277 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
278 if (ioctl_I_PUSH(slavefd,
"ptem") == -1)
goto error;
279 if (ioctl_I_PUSH(slavefd,
"ldterm") == -1)
goto error;
280 if (ioctl_I_PUSH(slavefd,
"ttcompat") == -1)
goto error;
289 if (slavefd != -1)
close(slavefd);
290 if (masterfd != -1)
close(masterfd);
295 #elif defined HAVE_OPENPTY
300 if (openpty(master, slave, SlaveName,
301 (
struct termios *)0, (
struct winsize *)0) == -1) {
302 if (!
fail)
return -1;
307 if (no_mesg(SlaveName, nomesg) == -1) {
308 if (!
fail)
return -1;
314 #elif defined HAVE__GETPTY
317 mode_t mode = nomesg ? 0600 : 0622;
319 if (!(
name = _getpty(master, O_RDWR, mode, 0))) {
320 if (!
fail)
return -1;
331 #elif defined(HAVE_PTSNAME)
333 int masterfd = -1, slavefd = -1;
342 if((masterfd = open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
352 if (no_mesg(slavedevice, nomesg) == -1)
goto error;
355 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
356 if(ioctl_I_PUSH(slavefd,
"ptem") == -1)
goto error;
357 if(ioctl_I_PUSH(slavefd,
"ldterm") == -1)
goto error;
358 ioctl_I_PUSH(slavefd,
"ttcompat");
366 if (slavefd != -1)
close(slavefd);
367 if (masterfd != -1)
close(masterfd);
372 int masterfd = -1, slavefd = -1;
377 c"0",c"1",c"2",c"3",c"4",c"5",c"6",c"7", \
378 c"8",c"9",c"a",c"b",c"c",c"d",c"e",c"f"
381 static const char MasterDevice[] =
"/dev/ptym/pty%s";
382 static const char SlaveDevice[] =
"/dev/pty/tty%s";
383 static const char deviceNo[][3] = {
387 #elif defined(_IBMESA)
388 static const char MasterDevice[] =
"/dev/ptyp%s";
389 static const char SlaveDevice[] =
"/dev/ttyp%s";
390 static const char deviceNo[][3] = {
397 static const char MasterDevice[] =
"/dev/pty%s";
398 static const char SlaveDevice[] =
"/dev/tty%s";
399 static const char deviceNo[][3] = {
405 const char *
const devno = deviceNo[
i];
406 snprintf(MasterName,
sizeof MasterName, MasterDevice, devno);
415 if (
chmod(SlaveName, nomesg ? 0600 : 0622) != 0)
goto error;
422 if (slavefd != -1)
close(slavefd);
423 if (masterfd != -1)
close(masterfd);
430 getDevice(
int *master,
int *slave,
char SlaveName[
DEVICELEN],
int nomesg)
432 if (get_device_once(master, slave, SlaveName, nomesg, 0)) {
434 get_device_once(master, slave, SlaveName, nomesg, 1);
439 pty_close_pty(
VALUE assoc)
444 for (
i = 0;
i < 2;
i++) {
495 int master_fd, slave_fd;
497 VALUE master_io, slave_file;
498 rb_io_t *master_fptr, *slave_fptr;
501 getDevice(&master_fd, &slave_fd, slavename, 1);
506 master_fptr->
fd = master_fd;
512 slave_fptr->
fd = slave_fd;
523 pty_detach_process(
VALUE v)
576 establishShell(
argc,
argv, &info, SlaveName);
587 wfptr->pathv = rfptr->pathv;
603 raise_from_check(
rb_pid_t pid,
int status)
609 #if defined(WIFSTOPPED)
610 #elif defined(IF_STOPPED)
611 #define WIFSTOPPED(status) IF_STOPPED(status)
613 ---->> Either IF_STOPPED or
WIFSTOPPED is needed <<----
618 else if (
kill(pid, 0) == 0) {
624 msg =
rb_sprintf(
"pty - %s: %ld", state, (
long)pid);
664 if (cpid == -1 || cpid == 0)
return Qnil;
667 raise_from_check(cpid, status);
NORETURN(static void raise_from_check(rb_pid_t pid, int status))
void rb_execarg_parent_end(VALUE execarg_obj)
int rb_cloexec_dup(int oldfd)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE rb_exc_new_str(VALUE etype, VALUE str)
VALUE rb_last_status_get(void)
void rb_execarg_parent_start(VALUE execarg_obj)
int rb_block_given_p(void)
Determines if the current method is given a block.
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)
void rb_ary_store(VALUE ary, long idx, VALUE val)
#define RB_TYPE_P(obj, type)
VALUE rb_define_module(const char *name)
void rb_fd_fix_cloexec(int fd)
struct rb_execarg * eargp
#define WIFSTOPPED(status)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
int chown(const char *, int, int)
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_ary_entry(VALUE ary, long offset)
VALUE rb_ivar_get(VALUE, ID)
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
VALUE rb_detach_process(rb_pid_t pid)
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
void rb_update_max_fd(int fd)
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
void rb_sys_fail(const char *mesg)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
RUBY_EXTERN int dup2(int, int)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
VALUE rb_sprintf(const char *format,...)
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
int rb_io_modestr_fmode(const char *modestr)
#define MakeOpenFile(obj, fp)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
#define UNREACHABLE_RETURN(val)
VALUE rb_iv_set(VALUE, const char *, VALUE)