1 /*
2 * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
3 * Copyright (c) 1996-2005 Michael T Pins. All rights reserved.
4 *
5 * UNIX command execution.
6 */
7
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <errno.h>
13 #include <sys/wait.h>
14 #include <string.h>
15 #include "config.h"
16 #include "global.h"
17 #include "execute.h"
18 #include "folder.h"
19 #include "nn_term.h"
20
21
22 /* execute.c */
23
24 static int shell_check(void);
25
26
27 int shell_restrictions = 0; /* disable shell escapes */
28
29 static char *init_shell = SHELL;
30 char *user_shell;
31 char *exec_chdir_to = NULL;
32
33
34
35 static int
shell_check(void)36 shell_check(void)
37 {
38 if (shell_restrictions) {
39 msg("Restricted operation - not allowed");
40 return -1;
41 }
42 return 0;
43 }
44
45 void
init_execute(void)46 init_execute(void)
47 {
48 if ((user_shell = getenv("SHELL")) == NULL)
49 user_shell = SHELL;
50 }
51
52 int
execute(char * path,char ** args,int toggle_visual)53 execute(char *path, char **args, int toggle_visual)
54 {
55 int was_raw, pid, i, status;
56 sig_type(*quit) (), (*intr) (), (*tstp) ();
57
58 was_raw = toggle_visual ? visual_off() : unset_raw();
59
60 while ((pid = fork()) == -1)
61 sleep(1);
62
63 if (pid == 0) {
64 for (i = 3; i < 20; i++)
65 close(i);
66
67 if (exec_chdir_to != NULL)
68 chdir(exec_chdir_to);
69
70 if (execvp(path, args)) {
71 msg("%s: %s", path, strerror(errno));
72 user_delay(2);
73 exit(20);
74 }
75 }
76 quit = signal(SIGQUIT, SIG_IGN);
77 intr = signal(SIGINT, SIG_IGN);
78
79 #ifdef HAVE_JOBCONTROL
80 tstp = signal(SIGTSTP, SIG_DFL);
81 #endif
82
83 while ((i = wait(&status)) != pid && (i != -1 || errno == EINTR));
84
85 signal(SIGQUIT, quit);
86 signal(SIGINT, intr);
87
88 #ifdef HAVE_JOBCONTROL
89 signal(SIGTSTP, tstp);
90 #endif
91
92 if (toggle_visual) {
93 visual_on();
94 if (toggle_visual == 2)
95 s_redraw++;
96 }
97 if (was_raw)
98 nn_raw();
99
100 return (status & 0xff) ? 0x100 : (status >> 8);
101 }
102
103
104 int
shell_escape(void)105 shell_escape(void)
106 {
107 static char command[FILENAME] = "";
108 char *cmd;
109 int first = 1;
110
111 if (shell_check())
112 return 0;
113
114 for (;;) {
115 prompt("\1!\1");
116 cmd = get_s(command, NONE, NONE, NULL_FCT);
117 if (cmd == NULL)
118 return !first;
119
120 if (*cmd == NUL) {
121 if (first)
122 run_shell((char *) NULL, 1, 0);
123 return 1;
124 }
125 strcpy(command, cmd);
126
127 if (run_shell(command, first, 0) < 0)
128 return !first;
129 first = 0;
130 prompt_line = -1;
131 }
132 }
133
134
135 static char *exec_sh_args[] = {
136 "nnsh",
137 (char *) NULL, /* "-c" or "-i" */
138 (char *) NULL, /* cmdstring */
139 (char *) NULL
140 };
141
142 int
run_shell(char * command,int clear,int init_sh)143 run_shell(char *command, int clear, int init_sh)
144
145 /*
146 * clear -2 => no command output (:!!command) - keep visual, output
147 * before command: -1 => none, 0 => CR/NL, 1 => clear
148 */
149 /* init_sh 0 => use user_shell, else use init_shell */
150 {
151 char cmdstring[512];
152
153 if (shell_check())
154 return -1;
155
156 if (command != NULL) {
157 if (!expand_file_name(cmdstring, command, 1))
158 return -1;
159 exec_sh_args[1] = "-c";
160 exec_sh_args[2] = cmdstring;
161 } else {
162 exec_sh_args[1] = "-i";
163 exec_sh_args[2] = NULL;
164 }
165
166 if (clear > 0) {
167 clrdisp();
168 fl;
169 } else if (clear == 0) {
170 tputc(CR);
171 tputc(NL);
172 }
173 return execute(init_sh ? init_shell : user_shell,
174 exec_sh_args, clear == -2 ? 0 : 1);
175 }
176
177 #ifndef HAVE_JOBCONTROL
178 static char *exec_suspend_args[] = {
179 "nnsh",
180 "-i",
181 (char *) NULL
182 };
183
184 #endif
185
186 int
suspend_nn(void)187 suspend_nn(void)
188 {
189 int was_raw;
190
191 if (shell_check())
192 return 0;
193
194 gotoxy(0, Lines - 1);
195 clrline();
196
197 #ifdef HAVE_JOBCONTROL
198 was_raw = visual_off();
199 kill(process_id, SIGSTOP);
200 visual_on();
201 s_redraw++;
202 if (was_raw)
203 nn_raw();
204 #else
205 execute(user_shell, exec_suspend_args, 2);
206 #endif
207
208 return 1;
209 }
210