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