| 30 |
************************************************************************/ |
************************************************************************/ |
| 31 |
|
|
| 32 |
#include <ncurses.h> /* does not build without it on BSD */ |
#include <ncurses.h> /* does not build without it on BSD */ |
| 33 |
|
#include <string.h> /* strlen */ |
| 34 |
#include <stdlib.h> |
#include <stdlib.h> |
| 35 |
#include <stdio.h> |
#include <stdio.h> |
| 36 |
#include <termios.h> |
#include <termios.h> |
| 43 |
#include "subshell.h" |
#include "subshell.h" |
| 44 |
|
|
| 45 |
static pid_t child_pid; |
static pid_t child_pid; |
| 46 |
//static int sub_pipe[2]; |
/* static int sub_pipe[2]; */ |
| 47 |
static int sub_pty, slave_pty; |
static int sub_pty, slave_pty; |
| 48 |
static struct termios shell_mode; |
static struct termios shell_mode; |
| 49 |
static int disable_output; |
static int disable_output; |
| 63 |
|
|
| 64 |
if (child_pid==0) { |
if (child_pid==0) { |
| 65 |
/* looking for terminals */ |
/* looking for terminals */ |
| 66 |
i=0; |
i = 0; |
| 67 |
do { |
do { |
| 68 |
sprintf(pty_name,"/dev/ptyp%x",i); |
sprintf(pty_name,"/dev/ptyp%x",i); |
| 69 |
sub_pty=open(pty_name,O_RDWR); |
sub_pty = open(pty_name, O_RDWR); |
| 70 |
if (sub_pty>0) { |
if ( sub_pty > 0) { |
| 71 |
pty_name[5]='t'; |
pty_name[5] = 't'; |
| 72 |
slave_pty=open(pty_name,O_RDWR); |
slave_pty = open (pty_name, O_RDWR); |
| 73 |
if (sub_pty>0 && slave_pty>0) break; |
if (sub_pty > 0 && slave_pty > 0) |
| 74 |
else close(sub_pty); |
break; |
| 75 |
pty_name[5]='p'; |
else |
| 76 |
} |
close (sub_pty); |
| 77 |
if (errno==ENOENT && (sub_pty<0 || slave_pty<0)) { |
pty_name[5] = 'p'; |
| 78 |
perror("open"); |
} |
| 79 |
fflush(NULL); |
if (errno == ENOENT && (sub_pty < 0 || slave_pty < 0)) { |
| 80 |
|
perror ("open"); |
| 81 |
|
fflush (NULL); |
| 82 |
return -1; |
return -1; |
| 83 |
} |
} |
| 84 |
if (i==0xf && pty_name[8]!='e') { |
if (i == 0xf && pty_name[8] != 'e') { |
| 85 |
if (pty_name[8]=='z') pty_name[8]='a'; |
if (pty_name[8] == 'z') pty_name[8] = 'a'; |
| 86 |
else pty_name[8]++; |
else pty_name[8]++; |
| 87 |
i=-1; |
i = -1; |
| 88 |
} |
} |
| 89 |
} while (0xf-i++); |
} while (0xf - i++); |
| 90 |
|
|
| 91 |
if (sub_pty<0 || slave_pty<0) { |
if (sub_pty < 0 || slave_pty < 0) { |
| 92 |
close(sub_pty); |
close (sub_pty); |
| 93 |
close(slave_pty); |
close (slave_pty); |
| 94 |
fprintf(stderr,"No pty available.\n"); |
fprintf (stderr, "No pty available.\n"); |
| 95 |
return (-1); |
return (-1); |
| 96 |
} |
} |
| 97 |
/* if (pipe(sub_pipe)) { |
/* if (pipe(sub_pipe)) { |
| 101 |
|
|
| 102 |
tcgetattr (STDOUT_FILENO, &shell_mode); |
tcgetattr (STDOUT_FILENO, &shell_mode); |
| 103 |
|
|
| 104 |
child_pid=fork(); |
child_pid = fork(); |
| 105 |
if (child_pid<0) { |
if (child_pid < 0) { |
| 106 |
perror("fork"); |
perror ("fork"); |
| 107 |
fflush(NULL); |
fflush (NULL); |
| 108 |
} else if (child_pid==0) { |
} else if (child_pid == 0) { |
| 109 |
setsid(); |
setsid (); |
| 110 |
slave_pty=open(pty_name,O_RDWR); |
slave_pty = open(pty_name, O_RDWR); |
| 111 |
if (slave_pty<0) { |
if (slave_pty < 0) { |
| 112 |
perror("open"); |
perror ("open"); |
| 113 |
exit(0); |
exit (0); |
| 114 |
} |
} |
| 115 |
close(sub_pty); |
close (sub_pty); |
| 116 |
|
|
| 117 |
# ifdef TIOCSCTTY |
# ifdef TIOCSCTTY |
| 118 |
ioctl (slave_pty, TIOCSCTTY, 0); |
ioctl (slave_pty, TIOCSCTTY, 0); |
| 121 |
shell_mode.c_lflag |= TOSTOP; |
shell_mode.c_lflag |= TOSTOP; |
| 122 |
tcsetattr (slave_pty, TCSANOW, &shell_mode); |
tcsetattr (slave_pty, TCSANOW, &shell_mode); |
| 123 |
|
|
| 124 |
putenv("HISTCONTROL=ignorespace"); |
putenv ("HISTCONTROL=ignorespace"); |
| 125 |
putenv("PS1=ofm-sh:\\w$ "); |
putenv ("PS1=ofm-sh:\\w$ "); |
| 126 |
|
|
| 127 |
dup2 (slave_pty, STDIN_FILENO); |
dup2 (slave_pty, STDIN_FILENO); |
| 128 |
dup2 (slave_pty, STDOUT_FILENO); |
dup2 (slave_pty, STDOUT_FILENO); |
| 129 |
dup2 (slave_pty, STDERR_FILENO); |
dup2 (slave_pty, STDERR_FILENO); |
| 130 |
// close (sub_pipe[0]); |
/* close (sub_pipe[0]); */ |
| 131 |
close (slave_pty); |
close (slave_pty); |
| 132 |
|
|
| 133 |
execl("/bin/sh","sh",NULL); |
execl ("/bin/sh", "sh", NULL); |
| 134 |
} /* else if (child_pid==0) */ |
} /* else if (child_pid==0) */ |
| 135 |
|
|
| 136 |
close(slave_pty); |
close (slave_pty); |
| 137 |
pid = waitpid (child_pid, &status, WUNTRACED | WNOHANG); |
pid = waitpid (child_pid, &status, WUNTRACED | WNOHANG); |
| 138 |
write(sub_pty, "cd ", 3); |
write (sub_pty, "cd ", 3); |
| 139 |
write(sub_pty, work_dir, strlen(work_dir)); |
write (sub_pty, work_dir, strlen (work_dir)); |
| 140 |
write(sub_pty, "\n", 1); |
write (sub_pty, "\n", 1); |
| 141 |
disable_output=2; |
disable_output=2; |
| 142 |
|
|
| 143 |
|
|
| 147 |
shell_mode.c_lflag &= ~ECHO; |
shell_mode.c_lflag &= ~ECHO; |
| 148 |
shell_mode.c_lflag &= ~OPOST; |
shell_mode.c_lflag &= ~OPOST; |
| 149 |
shell_mode.c_lflag &= ~ICANON; |
shell_mode.c_lflag &= ~ICANON; |
| 150 |
shell_mode.c_cc[VTIME]=0; |
shell_mode.c_cc[VTIME] = 0; |
| 151 |
shell_mode.c_cc[VMIN]=1; |
shell_mode.c_cc[VMIN] = 1; |
| 152 |
tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); |
tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); |
| 153 |
|
|
| 154 |
# if defined TIOCSWINSZ && !defined SCO_FLAVOR |
# if defined TIOCSWINSZ && !defined SCO_FLAVOR |
| 163 |
} |
} |
| 164 |
# endif |
# endif |
| 165 |
|
|
| 166 |
if (command!=NULL) { |
if (command != NULL) { |
| 167 |
write(sub_pty, "cd ", 3); |
write (sub_pty, "cd ", 3); |
| 168 |
write(sub_pty, work_dir, strlen(work_dir)); |
write (sub_pty, work_dir, strlen (work_dir)); |
| 169 |
write(sub_pty, "\n", 1); |
write (sub_pty, "\n", 1); |
| 170 |
write(sub_pty,command,strlen(command)); |
write (sub_pty,command,strlen (command)); |
| 171 |
write(sub_pty,"\n",1); |
write (sub_pty,"\n",1); |
| 172 |
disable_output++; |
disable_output++; |
| 173 |
} else { |
} else { |
| 174 |
write(sub_pty, "cd .\n", 5); |
write (sub_pty, "cd .\n", 5); |
| 175 |
disable_output++; |
disable_output++; |
| 176 |
} |
} |
| 177 |
|
|
| 178 |
/* setting time for select */ |
/* setting time for select */ |
| 179 |
if (switch_key>0) { |
if (switch_key > 0) { |
| 180 |
wtime.tv_sec = 10; |
wtime.tv_sec = 10; |
| 181 |
wtime.tv_usec = 0; |
wtime.tv_usec = 0; |
| 182 |
} else { |
} else { |
| 183 |
wtime.tv_sec = 0; |
wtime.tv_sec = 0; |
| 184 |
wtime.tv_usec = 200; |
wtime.tv_usec = 200; |
| 185 |
} |
} |
| 186 |
wptr=&wtime; |
wptr = &wtime; |
| 187 |
|
|
| 188 |
i=10; |
i = 10; |
| 189 |
while (1) { |
while (1) { |
| 190 |
FD_ZERO (&read_set); |
FD_ZERO (&read_set); |
| 191 |
FD_SET (sub_pty, &read_set); |
FD_SET (sub_pty, &read_set); |
| 192 |
// FD_SET (sub_pipe[0], &read_set); |
/* FD_SET (sub_pipe[0], &read_set); */ |
| 193 |
if (switch_key>0) FD_SET (STDIN_FILENO, &read_set); |
if (switch_key > 0) FD_SET (STDIN_FILENO, &read_set); |
| 194 |
|
|
| 195 |
if (select (FD_SETSIZE, &read_set, NULL, NULL, wptr)==-1) { |
if (select (FD_SETSIZE, &read_set, NULL, NULL, wptr)==-1) { |
| 196 |
if (errno==EINTR) { |
if (errno == EINTR) { |
| 197 |
continue; |
continue; |
| 198 |
} |
} |
| 199 |
tcsetattr(STDOUT_FILENO, TCSANOW, &shell_mode); |
tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); |
| 200 |
perror("select"); |
perror ("select"); |
| 201 |
return (-1); |
return (-1); |
| 202 |
} |
} |
| 203 |
|
|
| 204 |
if (FD_ISSET (sub_pty, &read_set)) { |
if (FD_ISSET (sub_pty, &read_set)) { |
| 205 |
bytes = read (sub_pty, buff, sizeof(buff)); |
bytes = read (sub_pty, buff, sizeof(buff)); |
| 206 |
if (bytes==-1) { |
if (bytes == -1) { |
| 207 |
tcsetattr(STDOUT_FILENO, TCSANOW, &shell_mode); |
tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); |
| 208 |
perror("reading from pseudo terminal"); |
perror ("reading from pseudo terminal"); |
| 209 |
pid = waitpid (child_pid, &status, WUNTRACED | WNOHANG); |
pid = waitpid (child_pid, &status, WUNTRACED | WNOHANG); |
| 210 |
if (WIFEXITED(status) || WIFSIGNALED(status)) { |
if (WIFEXITED (status) || WIFSIGNALED (status)) { |
| 211 |
fprintf(stderr,"Subshell process exited.\n"); |
fprintf (stderr,"Subshell process exited.\n"); |
|
child_pid=0; |
|
|
close(sub_pty); |
|
|
// close(sub_pipe[0]); |
|
|
// close(sub_pipe[1]); |
|
|
} |
|
|
if (pid==-1 && errno==ECHILD) { |
|
|
fprintf(stderr,"Subshell process not exists.\n"); |
|
| 212 |
child_pid=0; |
child_pid=0; |
| 213 |
|
close (sub_pty); |
| 214 |
|
/* close(sub_pipe[0]); |
| 215 |
|
* close(sub_pipe[1]); |
| 216 |
|
*/ |
| 217 |
|
} |
| 218 |
|
if (pid == -1 && errno == ECHILD) { |
| 219 |
|
fprintf (stderr,"Subshell process not exists.\n"); |
| 220 |
|
child_pid = 0; |
| 221 |
} |
} |
| 222 |
return (-1); |
return (-1); |
| 223 |
} |
} |
| 224 |
if (disable_output==0) write (STDOUT_FILENO, buff, bytes); |
if (disable_output == 0) write (STDOUT_FILENO, buff, bytes); |
| 225 |
else if (buff[bytes-1]=='\n') disable_output--; |
else if (buff[bytes-1] == '\n') |
| 226 |
|
disable_output--; |
| 227 |
} /*else if (FD_ISSET (sub_pipe[0], &read_set)) { |
} /*else if (FD_ISSET (sub_pipe[0], &read_set)) { |
| 228 |
bytes = read (sub_pipe[0], buff, sizeof(buff)); |
bytes = read (sub_pipe[0], buff, sizeof(buff)); |
| 229 |
if (bytes==-1) { |
if (bytes==-1) { |
| 234 |
if (bytes >= 1) |
if (bytes >= 1) |
| 235 |
buff[bytes-1] = 0; |
buff[bytes-1] = 0; |
| 236 |
write (STDOUT_FILENO, buff, bytes); |
write (STDOUT_FILENO, buff, bytes); |
| 237 |
//fflush(stdout); |
fflush(stdout); |
| 238 |
|
|
| 239 |
}*/ else if (FD_ISSET (STDIN_FILENO, &read_set)) { |
}*/ |
| 240 |
bytes = read (STDIN_FILENO, buff, sizeof(buff)); |
else if (FD_ISSET (STDIN_FILENO, &read_set)) { |
| 241 |
if (bytes==-1) { |
bytes = read (STDIN_FILENO, buff, sizeof (buff)); |
| 242 |
tcsetattr(STDOUT_FILENO, TCSANOW, &shell_mode); |
if (bytes == -1) { |
| 243 |
perror("reading from stdin"); |
tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); |
| 244 |
|
perror ("reading from stdin"); |
| 245 |
return (-1); |
return (-1); |
| 246 |
} |
} |
| 247 |
i=bytes; |
i=bytes; |
| 248 |
while (i--) { |
while (i--) { |
| 249 |
if (switch_key>0 && buff[i]==switch_key) { |
if (switch_key > 0 && buff[i] == switch_key) { |
| 250 |
write(sub_pty, buff, i); |
write (sub_pty, buff, i); |
| 251 |
return 0; |
return 0; |
| 252 |
} |
} |
| 253 |
} |
} |
| 254 |
write (sub_pty, buff, bytes); |
write (sub_pty, buff, bytes); |
| 255 |
} else if (switch_key<=0) return 0; |
} |
| 256 |
if (switch_key>0) wptr=NULL; |
else if (switch_key <= 0) |
| 257 |
|
return 0; |
| 258 |
|
if (switch_key > 0) wptr=NULL; |
| 259 |
} |
} |
| 260 |
return 0; |
return 0; |
| 261 |
} |
} |
| 262 |
|
|
| 263 |
int subshell_execute(char *command) |
int subshell_execute (char *command) |
| 264 |
{ |
{ |
| 265 |
if (command==NULL) return 0; |
if (command==NULL) return 0; |
| 266 |
subshell_run(0,"./",command); |
subshell_run(0,"./",command); |
| 267 |
// write(sub_pty, command, strlen(command)); |
/* write(sub_pty, command, strlen(command)); |
| 268 |
// write(sub_pty, "\n", 1); |
* write(sub_pty, "\n", 1); |
| 269 |
|
*/ |
| 270 |
return 0; |
return 0; |
| 271 |
} |
} |
| 272 |
|
|