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 |
|
|