A simple launcher
As a workaround for buffering issue of TurtleEdit, I wrote a simple launcher to cheat your code into belief that it is running in a terminal.
Usage
Download the C code below, then compile it in Mac or Linux (unfortunately, there is no Windows version) as
cc -o run run.c
Copy or move the executable file (run) into your programming folder.
Next, select Settings in Run menu of TurtleEdit, and modify "command for execution" as
./run ./a.out
in case of C. For Ruby, for example, setting is something like
./run ruby %f
Once this is done, you need not modify codes seen in textbooks when you use TurtleEdit.
Code
/* a simple program launcher for TurtleEdit */
/* Yoshinori Hayakawa, Tohoku University */
/* 07-MAY-2014 */
/* most of this code is based on the exmaples in */
/* http://rachid.koucha.free.fr/tech_corner/pty_pdip.html */
/* */
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFLEN 1024
char **cmdargv = NULL ;
char readbuf[BUFFLEN] ;
int terminating ;
void sigchld_handler(int);
int main(int argc, char *argv[]) {
int i,master,slave ;
pid_t pid ;
if (argc<=1) return 0 ;
else {
cmdargv = (char **) malloc(sizeof(char *)*argc) ;
for (i=1 ; i<argc ; i++) {
cmdargv[i-1] = argv[i] ;
}
cmdargv[argc-1]='\0' ;
}
master = open("/dev/ptmx", O_RDWR|O_NOCTTY);
grantpt(master);
unlockpt(master);
slave = open(ptsname(master), O_RDWR);
terminating = 0 ;
if (pid=fork()) { /* parent */
fd_set fd_input ;
int rc,k ;
signal(SIGCHLD, sigchld_handler);
close(slave) ;
while (1)
{
FD_ZERO(&fd_input);
FD_SET(0, &fd_input);
FD_SET(master, &fd_input);
rc = select(master + 1, &fd_input, NULL, NULL, NULL);
switch(rc)
{
case -1 :
exit(0);
default :
if (FD_ISSET(0, &fd_input)) { /* check stdin */
rc = read(0, readbuf, sizeof(readbuf));
if (rc > 0) {
write(master, readbuf, rc);
} else {
if (rc < 0) {
fprintf(stderr, "Error on read standard input\n");
exit(1);
}
}
}
if (FD_ISSET(master, &fd_input)) { /* check PTY */
rc = read(master, readbuf, sizeof(readbuf));
if (rc > 0) {
write(1, readbuf, rc);
}
if (terminating) exit(0) ;
}
}
}
}
else { /* child process */
struct termios term_setting ;
close(master) ;
dup2(slave,0) ;
dup2(slave,1) ;
dup2(slave,2) ;
/* disable echo */
tcgetattr (0, &term_setting) ;
term_setting.c_lflag &= ~ECHO;
term_setting.c_cc[VEOF] = 0x04 ; // CTRL-D
term_setting.c_cc[VERASE] = 0x08 ; // BACKSPACE
term_setting.c_lflag |= ICANON ;
tcsetattr (0, TCSAFLUSH, &term_setting) ;
setsid() ;
ioctl(0, TIOCSCTTY, 1);
if (execvp(argv[1],cmdargv)==-1) {
fprintf(stderr,"cannot execute %s\n",argv[1]) ;
}
_exit(0) ;
}
return 0 ;
}
void sigchld_handler(int x)
{
terminating = 1 ;
}