1 /******************************************************************************
2 * This file is part of TinTin++ *
3 * *
4 * Copyright 2004-2019 Igor van den Hoven *
5 * *
6 * TinTin++ is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with TinTin++. If not, see https://www.gnu.org/licenses. *
19 ******************************************************************************/
20
21 /******************************************************************************
22 * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t *
23 * *
24 * coded by Igor van den Hoven 2007 *
25 ******************************************************************************/
26
27 #include "tintin.h"
28
29 #ifdef HAVE_PTY_H
30 #include <pty.h>
31 #else
32 #ifdef HAVE_UTIL_H
33 #include <util.h>
34 #endif
35 #endif
36 #include <fcntl.h>
37 #include <dirent.h>
38 #include <termios.h>
39 #include <sys/un.h>
40 #include <sys/wait.h>
41 #include <signal.h>
42
DO_COMMAND(do_run)43 DO_COMMAND(do_run)
44 {
45 char temp[BUFFER_SIZE];
46 int desc, pid;
47 struct winsize size;
48
49 char *argv[4] = {"sh", "-c", "", NULL};
50
51 arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
52 arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
53 arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
54
55 if (*arg1 == 0 || *arg2 == 0)
56 {
57 show_error(ses, LIST_COMMAND, "#SYNTAX: #RUN {NAME} {SYSTEM SHELL COMMAND}");
58
59 return ses;
60 }
61
62 size.ws_row = get_scroll_rows(ses);
63 size.ws_col = get_scroll_cols(ses);
64 size.ws_ypixel = size.ws_row * gtd->screen->char_height;
65 size.ws_xpixel = size.ws_col * gtd->screen->char_width;
66
67 pid = forkpty(&desc, temp, >d->old_terminal, &size);
68
69 switch (pid)
70 {
71 case -1:
72 syserr_printf(ses, "do_run: forkpty");
73 break;
74
75 case 0:
76 sprintf(temp, "exec %s", arg2);
77 argv[2] = temp;
78 execv("/bin/sh", argv);
79 break;
80
81 default:
82 /*
83 if (fcntl(desc, F_SETFD, FD_CLOEXEC) == -1)
84 {
85 syserr_printf(ses, "do_run: fcntl");
86 }
87 */
88 sprintf(temp, "{%s} {%d} {%s}", arg2, pid, arg3);
89 ses = new_session(ses, arg1, temp, desc, 0);
90 break;
91 }
92 return ses;
93 }
94
95
DO_COMMAND(do_script)96 DO_COMMAND(do_script)
97 {
98 char *cptr, buf[BUFFER_SIZE], var[BUFFER_SIZE], tmp[BUFFER_SIZE];
99 FILE *script;
100 int index;
101
102 arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
103 arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
104
105 if (*arg1 == 0)
106 {
107 show_error(ses, LIST_COMMAND, "#SCRIPT: ONE ARGUMENT REQUIRED.");
108 }
109 else if (*arg2 == 0)
110 {
111 script = popen(arg1, "r");
112
113 if (script)
114 {
115 while (fgets(buf, BUFFER_SIZE - 1, script))
116 {
117 cptr = strchr(buf, '\n');
118
119 if (cptr)
120 {
121 *cptr = 0;
122 }
123
124 ses = script_driver(ses, LIST_COMMAND, buf);
125 }
126
127 pclose(script);
128 }
129 else
130 {
131 syserr_printf(ses, "do_script: popen 1");
132 }
133 }
134 else
135 {
136 index = 1;
137
138 script = popen(arg2, "r");
139
140 if (script)
141 {
142 var[0] = 0;
143
144 while (fgets(buf, BUFFER_SIZE - 1, script))
145 {
146 cptr = strchr(buf, '\n');
147
148 if (cptr)
149 {
150 *cptr = 0;
151 }
152
153 substitute(ses, buf, tmp, SUB_SEC);
154
155 cat_sprintf(var, "{%d}{%s}", index++, tmp);
156 }
157
158 set_nest_node_ses(ses, arg1, "%s", var);
159
160 pclose(script);
161 }
162 else
163 {
164 syserr_printf(ses, "do_script: popen 2");
165 }
166 }
167 refresh_session_terminal(ses);
168
169 return ses;
170 }
171
172
DO_COMMAND(do_suspend)173 DO_COMMAND(do_suspend)
174 {
175 print_stdout(0, 0, "\e[?1049l\e[r\e[%d;%dH", gtd->screen->rows, 1);
176
177 fflush(NULL);
178
179 reset_terminal(gtd->ses);
180
181 kill(0, SIGSTOP);
182
183 init_terminal(gtd->ses);
184
185 dirty_screen(gtd->ses);
186
187 tintin_printf(gtd->ses, "#RETURNING BACK TO TINTIN++.");
188
189 return ses;
190 }
191
192 // use #run + waitpid() ?
193
194 /*
195 DO_COMMAND(do_system)
196 {
197 char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], temp[BUFFER_SIZE], buffer[BUFFER_SIZE];
198 int desc, pid;
199 struct winsize size;
200 char *argv[4] = {"sh", "-c", "", NULL};
201 int filedes[2];
202
203 arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
204
205 if (*arg1 == 0)
206 {
207 show_error(ses, LIST_COMMAND, "#SYNTAX: #SYSTEM {SHELL COMMAND}");
208
209 return ses;
210 }
211
212 size.ws_row = get_scroll_rows(ses);
213 size.ws_col = get_scroll_cols(ses);
214 size.ws_ypixel = size.ws_row * gtd->screen->char_height;
215 size.ws_xpixel = size.ws_col * gtd->screen->char_width;
216
217 if (pipe(filedes) == -1)
218 {
219 perror("pipe");
220
221 return ses;
222 }
223
224 pid = fork();
225
226 switch (pid)
227 {
228 case -1:
229 syserr_printf(ses, "do_system: forkpty");
230 break;
231
232 case 0:
233 while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
234 close(filedes[1]);
235 close(filedes[0]);
236
237 sprintf(temp, "exec %s", arg1);
238 argv[2] = temp;
239 execv("/bin/sh", argv);
240 perror("execv");
241 break;
242
243 default:
244 close(filedes[1]);
245
246 while (TRUE)
247 {
248 ssize_t count = read(filedes[0], buffer, sizeof(buffer));
249
250 if (count == -1)
251 {
252 if (errno == EINTR)
253 {
254 continue;
255 }
256 else
257 {
258 perror("read");
259 }
260 return ses;
261 }
262 else if (count == 0)
263 {
264 break;
265 }
266 else
267 {
268 tintin_printf2(ses, "%s", buffer);
269 }
270 }
271 close(filedes[0]);
272 wait(0);
273 break;
274 }
275 return ses;
276 }
277 */
278
DO_COMMAND(do_system)279 DO_COMMAND(do_system)
280 {
281 sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
282
283 if (*arg1 == 0)
284 {
285 show_error(ses, LIST_COMMAND, "#SYNTAX: #SYSTEM {COMMAND}.");
286
287 return ses;
288 }
289
290 show_message(ses, LIST_COMMAND, "#OK: EXECUTING '%s'", arg1);
291
292 if (!HAS_BIT(gtd->ses->flags, SES_FLAG_READMUD) && IS_SPLIT(gtd->ses))
293 {
294 save_pos(gtd->ses);
295
296 goto_pos(gtd->ses, gtd->ses->split->bot_row, 1);
297 }
298
299 if (system(arg1) == -1)
300 {
301 syserr_printf(ses, "do_system: system:");
302 }
303
304 if (!HAS_BIT(gtd->ses->flags, SES_FLAG_READMUD) && IS_SPLIT(gtd->ses))
305 {
306 restore_pos(gtd->ses);
307 }
308
309 refresh_session_terminal(gtd->ses);
310
311 return ses;
312 }
313
314
DO_COMMAND(do_textin)315 DO_COMMAND(do_textin)
316 {
317 FILE *fp;
318 char buffer[BUFFER_SIZE], *cptr;
319
320 arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
321 arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
322
323 if ((fp = fopen(arg1, "r")) == NULL)
324 {
325 show_error(ses, LIST_COMMAND, "#ERROR: #TEXTIN {%s} - FILE NOT FOUND.", arg1);
326
327 return ses;
328 }
329
330 while (fgets(buffer, BUFFER_SIZE - 1, fp))
331 {
332 cptr = strchr(buffer, '\n');
333
334 if (cptr)
335 {
336 *cptr = 0;
337 }
338
339 write_mud(ses, buffer, SUB_EOL);
340
341 if (*arg2)
342 {
343 usleep((long long) (get_number(ses, arg2) * 1000000));
344 }
345 }
346 fclose(fp);
347
348 show_message(ses, LIST_COMMAND, "#TEXTIN {%s} - FILE READ.", arg1);
349
350 return ses;
351 }
352