C-Menu
0.2.9
A User Interface Toolkit
Toggle main menu visibility
Loading...
Searching...
No Matches
exec.c
Go to the documentation of this file.
1
/** @file exec.c
2
@brief Functions to execute external commands
3
@author Bill Waller
4
Copyright (c) 2025
5
MIT License
6
billxwaller@gmail.com
7
@date 2026-02-09
8
*/
9
10
/** @defgroup exec External Commands
11
@brief This module provides functions to execute external commands
12
@note handles terminal settings, signal handling, and error reporting to
13
ensure a smooth user experience when executing commands from within the
14
application. The main functions include full_screen_fork_exec,
15
full_screen_shell, and fork_exec, which manage the execution of commands
16
while maintaining the integrity of the application's user interface.
17
*/
18
19
#
include
<
cm
.
h
>
20
#
include
<
errno
.
h
>
21
#
include
<
fcntl
.
h
>
22
#
include
<
stddef
.
h
>
23
#
include
<
stdlib
.
h
>
24
#
include
<
string
.
h
>
25
#
include
<
sys
/
types
.
h
>
26
#
include
<
sys
/
wait
.
h
>
27
#
include
<
termios
.
h
>
28
#
include
<
unistd
.
h
>
29
30
int
full_screen_fork_exec
(
char
**);
31
int
full_screen_shell
(
char
*);
32
int
shell
(
char
*);
33
int
fork_exec
(
char
**);
34
int
nf_error
(
int
ec,
char
*s);
35
/** @brief Execute a command in full screen mode
36
@ingroup exec
37
@param argv - array of arguments for the command to execute
38
@return the return code from the executed command
39
@note Clear the screen,
40
@note move the cursor to the bottom, and refresh the screen before executing
41
the command.
42
@note After the command completes, clear the screen, move the cursor to the
43
top, refresh the screen, and restore the windows. */
44
int
full_screen_fork_exec
(
char
**argv) {
45
int
rc;
46
47
fflush(stderr);
48
wmove(stdscr, LINES - 1, 0);
49
rc =
fork_exec
(
argv
)
;
50
return
(rc);
51
}
52
/** @brief Execute a shell command in full screen mode
53
@ingroup exec
54
@param shellCmdPtr - pointer to the shell command string
55
@return the return code from the executed shell command
56
@note Clear the screen, move the cursor to the top, and refresh the screen
57
before executing the shell command. @note After the command completes,
58
restore the windows.
59
*/
60
int
full_screen_shell
(
char
*shellCmdPtr) {
61
int
rc;
62
63
fflush(stderr);
64
werase(stdscr);
65
wmove(stdscr, 0, 0);
66
wrefresh(stdscr);
67
rc =
shell
(
shellCmdPtr
)
;
68
touchwin(stdscr);
69
wnoutrefresh(stdscr);
70
restore_wins
(
)
;
71
wrefresh(stdscr);
72
return
(rc);
73
}
74
/** @brief Execute a shell command
75
@ingroup exec
76
@param shellCmdPtr - pointer to the shell command string
77
@return the return code from the executed shell command
78
@note Executes the command string using the user's shell.
79
@note If the SHELL environment variable is not set, use /bin/sh. */
80
int
shell
(
char
*shellCmdPtr) {
81
int
Eargc;
82
char
*Eargv[
MAXARGS
];
83
char
*shellPtr;
84
int
rc;
85
86
Eargc = 0;
87
shellPtr = getenv(
"SHELL"
);
88
if
(shellPtr ==
nullptr
|| *shellPtr ==
'\0'
)
89
shellPtr =
DEFAULTSHELL
;
90
Eargv[Eargc++] = strdup(shellPtr);
91
Eargv[Eargc++] =
"-c"
;
92
Eargv[Eargc++] = shellCmdPtr;
93
Eargv[Eargc++] =
nullptr
;
94
rc =
fork_exec
(
Eargv
)
;
95
free(Eargv[0]);
96
return
(rc);
97
}
98
/** @brief Fork and exec a command
99
@ingroup exec
100
@param argv - array of arguments for the command to execute
101
@return the return code from the executed command, or -1 on error
102
@note Captures and restores terminal settings around the fork and exec.
103
@note Sets signal handlers to default in the child process.
104
@note Waits for the child process to complete in the parent process.
105
@note Handles errors from fork and execvp, and reports child exit status.
106
@note Restores curses mode and keypad settings after execution.
107
@note Restores window states after execution.
108
@note Uses a temporary string buffer tmp_str for error messages.
109
@note Uses Perror for error reporting.
110
@note Uses sig_dfl_mode and sig_prog_mode for signal handling.
111
@note Uses capture_curses_tioctl and restore_curses_tioctl for terminal
112
settings.
113
@note Uses restore_shell_tioctl for shell terminal settings.
114
@note Uses waitpid to wait for the child process.
115
@note Uses WIFEXITED, WEXITSTATUS, WIFSIGNALED, and WTERMSIG to interpret
116
child status.
117
@note Uses keypad to manage keypad mode in curses.
118
@note Uses restore_wins to restore window states.
119
@note Uses errno for error codes.
120
@note Uses pid_t for process IDs.
121
@note Uses standard file descriptors STDIN_FILENO, STDOUT_FILENO,
122
STDERR_FILENO.
123
@note Uses execvp for executing the command.
124
@note Uses fork for creating a new process.
125
@note Uses ssnprintf for formatting error messages.
126
@note Uses switch-case for handling fork results.
127
@note Uses default shell if SHELL environment variable is not set. */
128
int
fork_exec
(
char
**argv) {
129
char
tmp_str[
MAXLEN
];
130
pid_t pid;
131
int
status;
132
int
rc;
133
134
if
(argv[0] == 0) {
135
Perror
(
"fork_exec: missing argument for execvp"
)
;
136
return
(-1);
137
}
138
capture_curses_tioctl
(
)
;
139
curs_set(1);
140
sig_dfl_mode
(
)
;
141
142
tmp_str[0] =
'\0'
;
143
pid = fork();
144
switch
(pid) {
145
case
-1:
// parent fork failed
146
sig_prog_mode
(
)
;
147
keypad(stdscr, true);
148
ssnprintf
(
tmp_str
,
sizeof
(tmp_str)
,
"fork failed: %s, errno: %d"
,
149
argv[0]
,
errno
)
;
150
Perror
(
tmp_str
)
;
151
return
(-1);
152
case
0:
// child
153
restore_shell_tioctl
(
)
;
154
werase(stdscr);
155
wrefresh(stdscr);
156
execvp(argv[0], argv);
157
restore_curses_tioctl
(
)
;
158
sig_prog_mode
(
)
;
159
keypad(stdscr, true);
160
ssnprintf
(
tmp_str
,
sizeof
(tmp_str)
,
"execvp failed: %s, errno: %d"
,
161
argv[0]
,
errno
)
;
162
Perror
(
tmp_str
)
;
163
exit(-1);
164
default
:
// parent
165
rc = 0;
166
restore_curses_tioctl
(
)
;
167
sig_prog_mode
(
)
;
168
waitpid(pid, &status, 0);
169
if
(WIFEXITED(status)) {
170
rc = WEXITSTATUS(status);
171
if
(rc != 0) {
172
keypad(stdscr, true);
173
ssnprintf
(
tmp_str
,
sizeof
(tmp_str)
,
174
"Child %s exited with status %d"
,
argv[0]
,
rc
)
;
175
}
176
}
else
{
177
if
(WIFSIGNALED(status)) {
178
rc = WTERMSIG(status);
179
keypad(stdscr, true);
180
ssnprintf
(
tmp_str
,
sizeof
(tmp_str)
,
181
"Child %s terminated by signal %d"
,
argv[0]
,
rc
)
;
182
}
else
{
183
keypad(stdscr, true);
184
ssnprintf
(
tmp_str
,
sizeof
(tmp_str)
,
185
"Child %s terminated abnormally"
,
argv[0]
)
;
186
}
187
}
188
break
;
189
}
190
restore_curses_tioctl
(
)
;
191
sig_prog_mode
(
)
;
192
touchwin(stdscr);
193
wnoutrefresh(stdscr);
194
wrefresh(stdscr);
195
restore_wins
(
)
;
196
tmp_str[0] =
'\0'
;
197
if
(tmp_str[0] !=
'\0'
) {
198
Perror
(
tmp_str
)
;
199
}
200
return
(rc);
201
}
DEFAULTSHELL
#define DEFAULTSHELL
Definition
cm.h:189
MAXARGS
#define MAXARGS
Definition
cm.h:30
nullptr
#define nullptr
Definition
cm.h:25
MAXLEN
#define MAXLEN
Definition
curskeys.c:15
restore_wins
void restore_wins()
Restore all windows after a screen resize.
Definition
dwin.c:939
nf_error
int nf_error(int, char *)
Display error message and wait for key press.
Definition
dwin.c:1325
Perror
int Perror(char *)
Display a simple error message window or print to stderr.
Definition
dwin.c:1115
fork_exec
int fork_exec(char **)
Fork and exec a command.
Definition
exec.c:128
shell
int shell(char *)
Execute a shell command.
Definition
exec.c:80
full_screen_fork_exec
int full_screen_fork_exec(char **)
Execute a command in full screen mode.
Definition
exec.c:44
full_screen_shell
int full_screen_shell(char *)
Execute a shell command in full screen mode.
Definition
exec.c:60
ssnprintf
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition
futil.c:156
restore_curses_tioctl
bool restore_curses_tioctl()
restore_curses_tioctl() - restore curses terminal settings
Definition
scriou.c:81
capture_curses_tioctl
bool capture_curses_tioctl()
capture_curses_tioctl() - capture curses terminal settings
Definition
scriou.c:68
restore_shell_tioctl
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
Definition
scriou.c:56
sig_dfl_mode
void sig_dfl_mode()
Set signal handlers to default behavior.
Definition
sig.c:42
sig_prog_mode
void sig_prog_mode()
Set up signal handlers for interrupt signals.
Definition
sig.c:62
exec.c
Generated by
1.17.0