Skip to content
This repository was archived by the owner on Feb 28, 2025. It is now read-only.

Commit 8444431

Browse files
committed
(init_subshell_precmd): switch from stack to heap allocation to avoid buffer size issues
Signed-off-by: Yury V. Zaytsev <[email protected]>
1 parent 5f1e01b commit 8444431

File tree

1 file changed

+42
-60
lines changed

1 file changed

+42
-60
lines changed

src/subshell/common.c

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,13 +1127,10 @@ pty_open_slave (const char *pty_name)
11271127
*
11281128
* @return initialized pre-command string
11291129
*/
1130-
1131-
static void
1132-
init_subshell_precmd (char *precmd, size_t buff_size)
1130+
static gchar *
1131+
init_subshell_precmd (void)
11331132
{
11341133
/*
1135-
* ATTENTION! Make sure that the buffer for precmd is big enough.
1136-
*
11371134
* Fallback precmd emulation that should work with virtually any shell.
11381135
* No real precmd functionality is required, no support for \x substitutions
11391136
* in PS1 is needed. For convenience, $HOME is replaced by ~ in PS1.
@@ -1185,8 +1182,7 @@ init_subshell_precmd (char *precmd, size_t buff_size)
11851182
switch (mc_global.shell->type)
11861183
{
11871184
case SHELL_BASH:
1188-
g_snprintf (
1189-
precmd, buff_size,
1185+
return g_strdup_printf (
11901186
" mc_print_command_buffer () { printf \"%%s\\\\n\" \"$READLINE_LINE\" >&%d; }\n"
11911187
" bind -x '\"\\e" SHELL_BUFFER_KEYBINDING "\":\"mc_print_command_buffer\"'\n"
11921188
" bind -x '\"\\e" SHELL_CURSOR_KEYBINDING
@@ -1200,69 +1196,58 @@ init_subshell_precmd (char *precmd, size_t buff_size)
12001196
"PS1='\\u@\\h:\\w\\$ '\n",
12011197
command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE],
12021198
subshell_pipe[WRITE]);
1203-
break;
12041199

12051200
case SHELL_ASH_BUSYBOX:
1206-
/* BusyBox ash needs a somewhat complicated precmd emulation via PS1, and it is vital
1207-
* that BB be built with active CONFIG_ASH_EXPAND_PRMT, but this is the default anyway.
1208-
*/
1209-
g_snprintf (precmd, buff_size, precmd_fallback, subshell_pipe[WRITE]);
1210-
break;
1201+
// BusyBox ash needs a somewhat complicated precmd emulation via PS1, and it is vital
1202+
// that BB be built with active CONFIG_ASH_EXPAND_PRMT, but this is the default anyway
1203+
return g_strdup_printf (precmd_fallback, subshell_pipe[WRITE]);
12111204

12121205
case SHELL_DASH:
1213-
/* Debian ash needs a precmd emulation via PS1, similar to BusyBox ash,
1214-
* but does not support escape sequences for user, host and cwd in prompt.
1215-
*/
1216-
g_snprintf (precmd, buff_size, precmd_fallback, subshell_pipe[WRITE]);
1217-
break;
1206+
// Debian ash needs a precmd emulation via PS1, similar to BusyBox ash,
1207+
// but does not support escape sequences for user, host and cwd in prompt
1208+
return g_strdup_printf (precmd_fallback, subshell_pipe[WRITE]);
12181209

12191210
case SHELL_MKSH:
12201211
// mksh doesn't support \x placeholders in PS1 and needs precmd emulation via PS1
1221-
g_snprintf (precmd, buff_size, precmd_fallback, subshell_pipe[WRITE]);
1222-
break;
1212+
return g_strdup_printf (precmd_fallback, subshell_pipe[WRITE]);
12231213

12241214
case SHELL_KSH:
1225-
// pdksh based variants support \x placeholders but not any "precmd" functionality.
1226-
g_snprintf (precmd, buff_size,
1227-
" PS1='$(pwd>&%d; kill -STOP $$)'"
1228-
"\"${PS1:-\\u@\\h:\\w\\$ }\"\n",
1229-
subshell_pipe[WRITE]);
1230-
break;
1215+
// pdksh based variants support \x placeholders but not any "precmd" functionality
1216+
return g_strdup_printf (" PS1='$(pwd>&%d; kill -STOP $$)'"
1217+
"\"${PS1:-\\u@\\h:\\w\\$ }\"\n",
1218+
subshell_pipe[WRITE]);
12311219

12321220
case SHELL_ZSH:
1233-
g_snprintf (precmd, buff_size,
1234-
" mc_print_command_buffer () { printf \"%%s\\\\n\" \"$BUFFER\" >&%d; }\n"
1235-
" zle -N mc_print_command_buffer\n"
1236-
" bindkey '^[" SHELL_BUFFER_KEYBINDING "' mc_print_command_buffer\n"
1237-
" mc_print_cursor_position () { echo $CURSOR >&%d}\n"
1238-
" zle -N mc_print_cursor_position\n"
1239-
" bindkey '^[" SHELL_CURSOR_KEYBINDING "' mc_print_cursor_position\n"
1240-
" _mc_precmd(){ pwd>&%d;kill -STOP $$ }; precmd_functions+=(_mc_precmd)\n"
1241-
"PS1='%%n@%%m:%%~%%# '\n",
1242-
command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]);
1243-
break;
1221+
return g_strdup_printf (
1222+
" mc_print_command_buffer () { printf \"%%s\\\\n\" \"$BUFFER\" >&%d; }\n"
1223+
" zle -N mc_print_command_buffer\n"
1224+
" bindkey '^[" SHELL_BUFFER_KEYBINDING "' mc_print_command_buffer\n"
1225+
" mc_print_cursor_position () { echo $CURSOR >&%d}\n"
1226+
" zle -N mc_print_cursor_position\n"
1227+
" bindkey '^[" SHELL_CURSOR_KEYBINDING "' mc_print_cursor_position\n"
1228+
" _mc_precmd(){ pwd>&%d;kill -STOP $$ }; precmd_functions+=(_mc_precmd)\n"
1229+
"PS1='%%n@%%m:%%~%%# '\n",
1230+
command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]);
12441231

12451232
case SHELL_TCSH:
1246-
g_snprintf (precmd, buff_size,
1247-
"set echo_style=both; "
1248-
"set prompt='%%n@%%m:%%~%%# '; "
1249-
"alias precmd 'echo -n;echo $cwd:q >>%s; kill -STOP $$'\n",
1250-
tcsh_fifo);
1251-
break;
1252-
case SHELL_FISH:
1253-
g_snprintf (precmd, buff_size,
1254-
" bind \\e" SHELL_BUFFER_KEYBINDING " 'commandline >&%d';"
1255-
"bind \\e" SHELL_CURSOR_KEYBINDING " 'commandline -C >&%d';"
1256-
"if not functions -q fish_prompt_mc;"
1257-
"functions -e fish_right_prompt;"
1258-
"functions -c fish_prompt fish_prompt_mc; end;"
1259-
"function fish_prompt;"
1260-
"echo \"$PWD\">&%d; fish_prompt_mc; kill -STOP $fish_pid; end\n",
1261-
command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]);
1262-
break;
1233+
return g_strdup_printf ("set echo_style=both; "
1234+
"set prompt='%%n@%%m:%%~%%# '; "
1235+
"alias precmd 'echo -n;echo $cwd:q >>%s; kill -STOP $$'\n",
1236+
tcsh_fifo);
12631237

1238+
case SHELL_FISH:
1239+
return g_strdup_printf (" bind \\e" SHELL_BUFFER_KEYBINDING " 'commandline >&%d';"
1240+
"bind \\e" SHELL_CURSOR_KEYBINDING " 'commandline -C >&%d';"
1241+
"if not functions -q fish_prompt_mc;"
1242+
"functions -e fish_right_prompt;"
1243+
"functions -c fish_prompt fish_prompt_mc; end;"
1244+
"function fish_prompt;"
1245+
"echo \"$PWD\">&%d; fish_prompt_mc; kill -STOP $fish_pid; end\n",
1246+
command_buffer_pipe[WRITE], command_buffer_pipe[WRITE],
1247+
subshell_pipe[WRITE]);
12641248
default:
1265-
break;
1249+
fprintf (stderr, "subshell: unknown shell type (%d), aborting!\r\n", mc_global.shell->type);
1250+
exit (EXIT_FAILURE);
12661251
}
12671252
}
12681253

@@ -1525,8 +1510,6 @@ init_subshell (void)
15251510
{
15261511
// This must be remembered across calls to init_subshell()
15271512
static char pty_name[BUF_SMALL];
1528-
// Must be considerably longer than BUF_SMALL (128) to support fancy shell prompts
1529-
char precmd[BUF_MEDIUM];
15301513

15311514
// Take the current (hopefully pristine) tty mode and make
15321515
// a raw mode based on it now, before we do anything else with it
@@ -1630,12 +1613,11 @@ init_subshell (void)
16301613
init_subshell_child (pty_name);
16311614
}
16321615

1633-
init_subshell_precmd (precmd, BUF_MEDIUM);
1634-
1616+
gchar *precmd = init_subshell_precmd ();
16351617
write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd));
1618+
g_free (precmd);
16361619

16371620
// Wait until the subshell has started up and processed the command
1638-
16391621
subshell_state = RUNNING_COMMAND;
16401622
tty_enable_interrupt_key ();
16411623
if (!feed_subshell (QUIETLY, TRUE))

0 commit comments

Comments
 (0)