1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

remove marshal/gtk/kconv

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1999-08-13 05:37:52 +00:00
parent 210367ec88
commit 0a64817fb8
124 changed files with 14604 additions and 10219 deletions

11
ext/pty/MANIFEST Normal file
View file

@ -0,0 +1,11 @@
MANIFEST
README
README.expect
README.expect.jp
README.jp
expect_sample.rb
extconf.rb
lib/expect.rb
pty.c
script.rb
shl.rb

93
ext/pty/README Normal file
View file

@ -0,0 +1,93 @@
pty extension version 0.3 by A.ito
1. Introduction
This extension module adds ruby a functionality to execute an
arbitrary command through pseudo tty (pty).
2. Install
Follow the instruction below.
(1) Execute
ruby extconf.rb
then Makefile is generated.
(3) Do make; make install.
3. What you can do
This extension module defines a module named PTY, which contains
following module fungtions:
getpty(command)
spawn(command)
This function reserves a pty, executes command over the pty
and returns an array. The return value is an array with three
elements. The first element in the array is for reading and the
second for writing. The third element is the process ID of the
child process. If this function is called with an iterator block,
the array is passed to the block as block parameters, and the
function itself returns nil.
While the process spawned by this function is active, SIGCHLD
is captured to handle the change of the child process. When the
child process is suspended or finished, an exception is raised.
As all SIGCHLD signal is captured and processed by PTY module,
you can't use other function or method which spawns subprosesses
(including signal() and IO.popen()) while the PTY subprocesses
are active. Otherwise, unexpected exception will occur. To avoid
this problem, see protect_signal() below.
If this function is called with an iterator block, SIGCHLD signal
is captured only within the block. Therefore, it is risky to use
File objects for PTY subprocess outside the iterator block.
protect_signal
This function takes an iterator block. Within the iterator block,
no exception is raised even if any subprocess is terminated.
This function is used to enable functions like system() or IO.popen()
while PTY subprocess is active. For example,
PTY.spawn("command_foo") do |r,w|
...
...
PTY.protect_signal do
system "some other commands"
end
...
end
disables to send exception when "some other commands" is
terminated.
reset_signal
Disables to handle SIGCHLD while PTY subprocess is active.
4. License
(C) Copyright 1998 by Akinori Ito.
This software may be redistributed freely for this purpose, in full
or in part, provided that this entire copyright notice is included
on any copies of this software and applications and derivations thereof.
This software is provided on an "as is" basis, without warranty of any
kind, either expressed or implied, as to any matter including, but not
limited to warranty of fitness of purpose, or merchantability, or
results obtained from use of this software.
5. Bug report
Please feel free to send E-mail to
aito@ei5sun.yz.yamagata-u.ac.jp
for any bug report, opinion, contribution, etc.

22
ext/pty/README.expect Normal file
View file

@ -0,0 +1,22 @@
README for expect
by A. Ito, 28 October, 1998
Expect library adds IO class a method called expect(), which
does similar act to tcl's expect extension.
The usage of the method is:
IO#expect(pattern,timeout=9999999)
where `pattern' is an instance of String or Regexp and `timeout'
is Fixnum, which can be omitted.
When the method is called without block, it waits until the
input which matches the pattern is obtained from the IO or the time
specified as the timeout passes. When the pattern is obtained from the
IO, the method returns an array. The first element of the array is the
entire string obtained from the IO until the pattern matches. The
following elements indicates the specific pattern which matched to the
anchor in the regular expression. If the method ends because of
timeout, it returns nil.
When the method is called with block, the array is passed as
the block parameter.

21
ext/pty/README.expect.jp Normal file
View file

@ -0,0 +1,21 @@
README for expect
by A. Ito, 28 October, 1998
Expectライブラリはtcl の expect パッケージと似たような機能を
IOクラスに追加します
追加されるメソッドの使い方は次の通りです.
IO#expect(pattern,timeout=9999999)
pattern は String か Regexp のインスタンスtimeout は Fixnum
のインスタンスですtimeout は省略できます.
このメソッドがブロックなしで呼ばれた場合,まずレシーバである
IOオブジェクトから pattern にマッチするパターンが読みこまれる
まで待ちます.パターンが得られたら,そのパターンに関する配列を
返します配列の最初の要素はpattern にマッチするまでに読みこ
まれた内容の文字列です2番目以降の要素はpattern の正規表現
の中にアンカーがあった場合に,そのアンカーにマッチする部分です.
もしタイムアウトが起きた場合はこのメソッドはnilを返します
このメソッドがブロック付きで呼ばれた場合には,マッチした要素の
配列がブロック引数として渡され,ブロックが評価されます.

89
ext/pty/README.jp Normal file
View file

@ -0,0 +1,89 @@
pty 拡張モジュール version 0.3 by A.ito
1. はじめに
この拡張モジュールは仮想tty (pty) を通して適当なコマンドを
実行する機能を ruby に提供します.
2. インストール
次のようにしてインストールしてください.
(1) ruby extconf.rb
を実行すると Makefile が生成されます.
(2) make; make install を実行してください.
3. 何ができるか
この拡張モジュールはPTY というモジュールを定義します.その中
には,次のようなモジュール関数が含まれています.
getpty(command)
spawn(command)
この関数は仮想ttyを確保し指定されたコマンドをその仮想tty
の向こうで実行し配列を返します戻り値は3つの要素からなる
配列です最初の要素は仮想ttyから読み出すためのIOオブジェクト
2番目は書きこむためのIOオブジェクト3番目は子プロセスのプロ
セスIDですこの関数がイテレータとして呼ばれた場合これらの
要素はブロックパラメータとして渡され関数自体はnilを返します
この関数によって作られたサブプロセスが動いている間,子プロセス
の状態を監視するために SIGCHLD シグナルを捕捉します.子プロセス
が終了したり停止した場合には,例外が発生します.この間,すべての
SIGCHLD が PTY モジュールのシグナルハンドラに捕捉されるので,
サブプロセスを生成する他の関数(system() とか IO.popen()など)を
使うと,予期しない例外が発生することがあります.これを防ぐため
には下記のprotect_signal()を参照してください.
この関数がブロックパラメータ付きで呼ばれた場合には,そのブロック
の中でのみ SIGCHLD が捕捉されます.したがって,ブロックパラメータ
として渡されたIOオブジェクトをブロックの外に持ち出して使うの
は勧められません.
protect_signal
この関数はイテレータです.ここで指定されたブロックの中では,
子プロセスが終了しても例外を発生しません.この関数を使うことで,
PTYの子プロセスが動いている間でもsystem()や IO.popen()などの
関数を安全に使うことができます.例えば,
PTY.spawn("command_foo") do |r,w|
...
...
PTY.protect_signal do
system "some other commands"
end
...
end
このような記述により,"some other commands" が終了したときに
例外が発生するのを防げます.
reset_signal
PTY の子プロセスが動いていても,そのプロセスの終了時に例外が発生
しないようにします.
4. 利用について
伊藤彰則が著作権を保有します.
ソースプログラムまたはドキュメントに元の著作権表示が改変されずに
表示されている場合に限り,誰でも,このソフトウェアを無償かつ著作
権者に無断で利用・配布・改変できます.利用目的は限定されていませ
ん.
このプログラムの利用・配布その他このプログラムに関係する行為によ
って生じたいかなる損害に対しても,作者は一切責任を負いません.
5. バグ報告等
バグレポートは歓迎します.
aito@ei5sun.yz.yamagata-u.ac.jp
まで電子メールでバグレポートをお送りください.

56
ext/pty/expect_sample.rb Normal file
View file

@ -0,0 +1,56 @@
#
# sample program of expect.rb
#
# by A. Ito
#
# This program reports the latest version of ruby interpreter
# by connecting to ftp server at netlab.co.jp.
#
require 'pty'
require 'expect'
fnames = []
PTY.spawn("ftp ftp.netlab.co.jp") do
|r_f,w_f,pid|
w_f.sync = true
$expect_verbose = true
r_f.expect(/^Name.*: /) do
w_f.print "ftp\n"
end
if !ENV['USER'].nil?
username = ENV['USER']
elsif !ENV['LOGNAME'].nil?
username = ENV['LOGNAME']
else
username = 'guest'
end
r_f.expect('word:') do
w_f.print username+"@\n"
end
r_f.expect("ftp> ") do
w_f.print "cd pub/lang/ruby\n"
end
r_f.expect("ftp> ") do
w_f.print "dir\n"
end
r_f.expect("ftp> ") do |output|
for x in output[0].split("\n")
if x =~ /(ruby.*\.tar\.gz)/ then
fnames.push $1
end
end
end
begin
w_f.print "quit\n"
rescue
end
end
print "The latest ruby interpreter is "
print fnames.sort.pop
print "\n"

10
ext/pty/extconf.rb Normal file
View file

@ -0,0 +1,10 @@
require 'mkmf'
have_header("sys/stropts.h")
have_func("setresuid")
$CFLAGS << "-DHAVE_DEV_PTMX" if /cygwin/ === PLATFORM
if have_func("openpty") or
have_func("_getpty") or
have_func("ioctl")
create_makefile('pty')
end

36
ext/pty/lib/expect.rb Normal file
View file

@ -0,0 +1,36 @@
$expect_verbose = false
class IO
def expect(pat,timeout=9999999)
buf = ''
case pat
when String
e_pat = Regexp.new(Regexp.quote(pat))
when Regexp
e_pat = pat
end
while true
if IO.select([self],nil,nil,timeout).nil? then
result = nil
break
end
c = getc.chr
buf << c
if $expect_verbose
STDOUT.print c
STDOUT.flush
end
if buf =~ e_pat then
result = [buf,$1,$2,$3,$4,$5,$6,$7,$8,$9]
break
end
end
if iterator? then
yield result
else
return result
end
nil
end
end

497
ext/pty/pty.c Normal file
View file

@ -0,0 +1,497 @@
#include "config.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#else
#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
#endif
#include <ctype.h>
#include <ruby.h>
#include <rubyio.h>
#include <signal.h>
#ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define DEVICELEN 16
#if !defined(HAVE_OPENPTY)
#ifdef __hpux
char *MasterDevice = "/dev/ptym/pty%s",
*SlaveDevice = "/dev/pty/tty%s",
*deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
"q0","q1","q2","q3","q4","q5","q6","q7",
"q8","q9","qa","qb","qc","qd","qe","qf",
"r0","r1","r2","r3","r4","r5","r6","r7",
"r8","r9","ra","rb","rc","rd","re","rf",
"s0","s1","s2","s3","s4","s5","s6","s7",
"s8","s9","sa","sb","sc","sd","se","sf",
"t0","t1","t2","t3","t4","t5","t6","t7",
"t8","t9","ta","tb","tc","td","te","tf",
"u0","u1","u2","u3","u4","u5","u6","u7",
"u8","u9","ua","ub","uc","ud","ue","uf",
"v0","v1","v2","v3","v4","v5","v6","v7",
"v8","v9","va","vb","vc","vd","ve","vf",
"w0","w1","w2","w3","w4","w5","w6","w7",
"w8","w9","wa","wb","wc","wd","we","wf",
0,
};
#else /* NOT HPUX */
#ifdef _IBMESA /* AIX/ESA */
char *MasterDevice = "/dev/ptyp%s",
*SlaveDevice = "/dev/ttyp%s",
*deviceNo[] = {
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
"30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
"40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
"50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
"60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
"70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
"80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
"90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
"a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
"b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
"c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
"d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
};
#else
char *MasterDevice = "/dev/pty%s",
*SlaveDevice = "/dev/tty%s",
*deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
"q0","q1","q2","q3","q4","q5","q6","q7",
"q8","q9","qa","qb","qc","qd","qe","qf",
"r0","r1","r2","r3","r4","r5","r6","r7",
"r8","r9","ra","rb","rc","rd","re","rf",
0,
};
#endif /* _IBMESA */
#endif /* HPUX */
#endif /* !defined(HAVE_OPENPTY) */
char SlaveName[DEVICELEN];
extern int errno;
#define MAX_PTY 16
static int n_pty,last_pty;
static int chld_pid[MAX_PTY];
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
# define seteuid(e) setreuid(-1, (e))
# else /* NOT HAVE_SETREUID */
# ifdef HAVE_SETRESUID
# define seteuid(e) setresuid(-1, (e), -1)
# else /* NOT HAVE_SETRESUID */
/* I can't set euid. (;_;) */
# endif /* HAVE_SETRESUID */
# endif /* HAVE_SETREUID */
#endif /* NO_SETEUID */
struct pty_info {
int fd;
pid_t child_pid;
};
static void
set_signal_action(action)
RETSIGTYPE (*action)();
{
#ifdef __hpux
struct sigvec sv;
/*
* signal SIGCHLD should be delivered on stop of the child
*/
sv.sv_handler = action;
sv.sv_mask = sigmask(SIGCHLD);
sv.sv_flags = SV_BSDSIG;
sigvector(SIGCHLD, &sv, (struct sigvec *) 0);
#else /* not HPUX */
#if defined(SA_NOCLDSTOP)
struct sigaction sa;
/*
* signal SIGCHLD should be delivered on stop of the child
* (for SVR4)
*/
sa.sa_handler = action;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGCHLD);
sa.sa_flags = 0; /* SA_NOCLDSTOP flag is removed */
sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
#else
signal(SIGCHLD,action);
#endif
#endif /* not HPUX */
}
static void
reset_signal_action()
{
set_signal_action(SIG_DFL);
}
static RETSIGTYPE
chld_changed()
{
int cpid;
int i,n = -1;
int statusp;
for (;;) {
#ifdef HAVE_WAITPID
cpid = waitpid(-1, &statusp, WUNTRACED|WNOHANG);
#else
cpid = wait3(&statusp, WUNTRACED|WNOHANG, 0);
#endif
if (cpid == 0 || cpid == -1)
return;
for (i = 0; i < last_pty; i++) {
if (chld_pid[i] == cpid) {
n = i;
goto catched;
}
}
rb_raise(rb_eRuntimeError, "fork: %d", cpid);
}
catched:
#ifdef IF_STOPPED
if (IF_STOPPED(statusp)) { /* suspend */
rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
}
#else
#ifdef WIFSTOPPED
if (WIFSTOPPED(statusp)) { /* suspend */
rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
}
#else
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
#endif /* WIFSTOPPED */
#endif /* IF_STOPPED */
if (n >= 0) {
chld_pid[n] = 0;
n_pty--;
if (n_pty == 0)
reset_signal_action();
}
rb_raise(rb_eRuntimeError, "Child_changed: %d",cpid);
}
static void getDevice _((int*, int*));
static void
establishShell(shellname, info)
char *shellname;
struct pty_info *info;
{
static int i,j,master,slave,currentPid;
char *p,*getenv();
struct passwd *pwent;
RETSIGTYPE chld_changed();
if (shellname[0] == '\0') {
if ((p = getenv("SHELL")) != NULL) {
shellname = p;
}
else {
pwent = getpwuid(getuid());
if (pwent && pwent->pw_shell)
shellname = pwent->pw_shell;
else
shellname = "/bin/sh";
}
}
getDevice(&master,&slave);
currentPid = getpid();
set_signal_action(chld_changed);
if((i = vfork()) < 0) {
rb_sys_fail("fork failed");
}
if(i == 0) { /* child */
int argc;
char *argv[1024];
currentPid = getpid();
/*
* Set free from process group and controlling terminal
*/
#ifdef HAVE_SETSID
(void) setsid();
#else /* HAS_SETSID */
# ifdef HAVE_SETPGRP
# ifdef SETGRP_VOID
if (setpgrp() == -1)
perror("setpgrp()");
# else /* SETGRP_VOID */
if (setpgrp(0, currentPid) == -1)
rb_sys_fail("setpgrp()");
if ((i = open("/dev/tty", O_RDONLY)) < 0)
rb_sys_fail("/dev/tty");
else {
if (ioctl(i, TIOCNOTTY, (char *)0))
perror("ioctl(TIOCNOTTY)");
close(i);
}
# endif /* SETGRP_VOID */
# endif /* HAVE_SETPGRP */
#endif /* HAS_SETSID */
/*
* obtain new controlling terminal
*/
#if defined(TIOCSCTTY)
close(master);
(void) ioctl(slave, TIOCSCTTY, (char *)0);
/* errors ignored for sun */
#else
close(slave);
slave = open(SlaveName, O_RDWR);
if (slave < 0) {
perror("open: pty slave");
_exit(1);
}
close(master);
#endif
dup2(slave,0);
dup2(slave,1);
dup2(slave,2);
close(slave);
seteuid(getuid());
argc = 0;
for (i = 0; shellname[i];) {
while (isspace(shellname[i])) i++;
for (j = i; shellname[j] && !isspace(shellname[j]); j++);
argv[argc] = (char*)xmalloc(j-i+1);
strncpy(argv[argc],&shellname[i],j-i);
argv[argc][j-i] = 0;
i = j;
argc++;
}
argv[argc] = NULL;
execvp(argv[0],argv);
sleep(1);
_exit(1);
}
close(slave);
if (n_pty == last_pty) {
chld_pid[n_pty] = i;
n_pty++;
last_pty++;
}
else {
for (j = 0; j < last_pty; j++) {
if (chld_pid[j] == 0) {
chld_pid[j] = i;
n_pty++;
}
}
}
info->child_pid = i;
info->fd = master;
}
#ifdef HAVE_OPENPTY
/*
* Use openpty(3) of 4.3BSD Reno and later,
* or the same interface function.
*/
static void
getDevice(master,slave)
int *master,*slave;
{
if (openpty(master, slave, SlaveName,
(struct termios *)0, (struct winsize *)0) == -1) {
rb_raise(rb_eRuntimeError, "openpty() failed");
}
}
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
static void
getDevice(master,slave)
int *master,*slave;
{
char *name;
if (!(name = _getpty(master, O_RDWR, 0622, 0))) {
rb_raise(rb_eRuntimeError, "_getpty() failed");
}
*slave = open(name, O_RDWR);
strcpy(SlaveName, name);
}
#else /* HAVE__GETPTY */
static void
getDevice(master,slave)
int *master,*slave;
{
char **p;
int i,j;
char MasterName[DEVICELEN];
#ifdef HAVE_DEV_PTMX
char *pn;
void (*s)();
extern char *ptsname(int);
extern int unlockpt(int);
extern int grantpt(int);
if((i = open("/dev/ptmx", O_RDWR, 0)) != -1) {
s = signal(SIGCHLD, SIG_DFL);
if(grantpt(i) != -1) {
signal(SIGCHLD, s);
if(unlockpt(i) != -1) {
if((pn = ptsname(i)) != NULL) {
if((j = open(pn, O_RDWR, 0)) != -1) {
#if defined I_PUSH
if(ioctl(j, I_PUSH, "ptem") != -1) {
if(ioctl(j, I_PUSH, "ldterm") != -1) {
#endif
*master = i;
*slave = j;
strcpy(SlaveName, pn);
return;
#if defined I_PUSH
}
}
#endif
}
}
}
}
close(i);
}
rb_raise(rb_eRuntimeError, "Cannot get Master/Slave device");
#else
for (p = deviceNo; *p != NULL; p++) {
sprintf(MasterName ,MasterDevice,*p);
if ((i = open(MasterName,O_RDWR,0)) >= 0) {
*master = i;
sprintf(SlaveName ,SlaveDevice,*p);
if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
*slave = j;
chown(SlaveName, getuid(), getgid());
chmod(SlaveName, 0622);
return;
}
close(i);
}
}
rb_raise(rb_eRuntimeError, "Cannot get %s\n", SlaveDevice);
#endif
}
#endif /* HAVE__GETPTY */
#endif /* HAVE_OPENPTY */
static void
freeDevice()
{
chmod(SlaveName, 0666);
chown(SlaveName, 0, 0);
}
/* ruby function: getpty */
static VALUE
pty_getpty(self, shell)
VALUE self, shell;
{
VALUE res;
struct pty_info info;
OpenFile *wfptr,*rfptr;
NEWOBJ(rport, struct RFile);
NEWOBJ(wport, struct RFile);
if (n_pty == MAX_PTY+1) {
rb_raise(rb_eRuntimeError, "Too many ptys are open");
}
OBJSETUP(rport, rb_cFile, T_FILE);
MakeOpenFile(rport, rfptr);
OBJSETUP(wport, rb_cFile, T_FILE);
MakeOpenFile(wport, wfptr);
establishShell(RSTRING(shell)->ptr,&info);
rfptr->mode = rb_io_mode_flags("r");
rfptr->f = fdopen(info.fd, "r");
rfptr->path = strdup(RSTRING(shell)->ptr);
wfptr->mode = rb_io_mode_flags("w");
wfptr->f = fdopen(dup(info.fd), "w");
wfptr->path = strdup(RSTRING(shell)->ptr);
res = rb_ary_new2(2);
rb_ary_store(res,0,(VALUE)rport);
rb_ary_store(res,1,(VALUE)wport);
rb_ary_store(res,2,INT2FIX(info.child_pid));
if (rb_iterator_p()) {
rb_yield((VALUE)res);
reset_signal_action();
return Qnil;
}
else {
return (VALUE)res;
}
}
/* ruby function: protect_signal */
static VALUE
pty_protect(self)
VALUE self;
{
reset_signal_action();
rb_yield(Qnil);
set_signal_action(chld_changed);
return self;
}
static VALUE
pty_reset_signal(self)
VALUE self;
{
reset_signal_action();
return self;
}
static VALUE cPTY;
void
Init_pty()
{
cPTY = rb_define_module("PTY");
rb_define_module_function(cPTY,"getpty",pty_getpty,1);
rb_define_module_function(cPTY,"spawn",pty_getpty,1);
rb_define_module_function(cPTY,"protect_signal",pty_protect,0);
rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0);
}

38
ext/pty/script.rb Normal file
View file

@ -0,0 +1,38 @@
require 'pty'
if ARGV.size == 0 then
ofile = "typescript"
else
ofile = ARGV[0]
end
logfile = File.open(ofile,"a")
system "stty -echo raw lnext ^_"
PTY.spawn("/bin/csh") do
|r_pty,w_pty,pid|
Thread.new do
while true
w_pty.print STDIN.getc.chr
w_pty.flush
end
end
begin
while true
c = r_pty.getc
next if c.nil?
print c.chr
STDOUT.flush
logfile.print c.chr
end
rescue
# print $@,':',$!,"\n"
logfile.close
end
end
system "stty echo -raw lnext ^v"

96
ext/pty/shl.rb Normal file
View file

@ -0,0 +1,96 @@
#
# old-fashioned 'shl' like program
# by A. Ito
#
# commands:
# c creates new shell
# C-z suspends shell
# p lists all shell
# 0,1,... choose shell
# q quit
require 'pty'
$shells = []
$n_shells = 0
$r_pty = nil
$w_pty = nil
def writer
PTY.protect_signal do
system "stty -echo raw"
end
begin
while true
c = STDIN.getc
if c == 26 then # C-z
$reader.raise(nil)
return 'Suspend'
end
$w_pty.print c.chr
$w_pty.flush
end
rescue
$reader.raise(nil)
return 'Exit'
ensure
PTY.protect_signal do
system "stty echo -raw"
end
end
end
$reader = Thread.new {
while true
begin
next if $r_pty.nil?
c = $r_pty.getc
if c.nil? then
Thread.stop
end
print c.chr
STDOUT.flush
rescue
Thread.stop
end
end
}
# $reader.raise(nil)
while true
print ">> "
STDOUT.flush
case gets
when /^c/i
$shells[$n_shells] = PTY.spawn("/bin/csh")
$r_pty,$w_pty = $shells[$n_shells]
$n_shells += 1
$reader.run
if writer == 'Exit'
$n_shells -= 1
$shells[$n_shells] = nil
end
when /^p/i
for i in 0..$n_shells
unless $shells[i].nil?
print i,"\n"
end
end
when /^([0-9]+)/
n = $1.to_i
if $shells[n].nil?
print "\##{i} doesn't exist\n"
else
$r_pty,$w_pty = $shells[n]
$reader.run
if writer == 'Exit' then
$shells[n] = nil
end
end
when /^q/i
exit
end
end