Ticket #2118: split exec_extention() function to few functions.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2012-03-06 22:37:30 +03:00
parent e944301b2a
commit 2af4c0d723
1 changed files with 236 additions and 181 deletions

View File

@ -85,61 +85,75 @@ typedef char *(*quote_func_t) (const char *name, int quote_percent);
* need it
*/
static char *data = NULL;
static vfs_path_t *localfilecopy_vpath = NULL;
static char buffer[BUF_1K];
static char *pbuffer = NULL;
static time_t localmtime = 0;
static quote_func_t quote_func = name_quote;
static gboolean run_view = FALSE;
static gboolean is_cd = FALSE;
static gboolean written_nonspace = FALSE;
/*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
static void
exec_extension (const char *filename, const char *lc_data, int *move_dir, int start_line)
exec_cleanup_file_name (vfs_path_t * filename_vpath, gboolean has_changed)
{
vfs_path_t *file_name_vpath;
int cmd_file_fd;
FILE *cmd_file;
char *cmd = NULL;
int expand_prefix_found = 0;
int parameter_found = 0;
char lc_prompt[80];
int run_view = 0;
int def_hex_mode = mcview_default_hex_mode, changed_hex_mode = 0;
int def_nroff_flag = mcview_default_nroff_flag, changed_nroff_flag = 0;
int written_nonspace = 0;
int is_cd = 0;
char buffer[1024];
char *p = 0;
vfs_path_t *localcopy_vpath = NULL;
int do_local_copy;
time_t localmtime = 0;
struct stat mystat;
quote_func_t quote_func = name_quote;
vfs_path_t *vpath;
if (localfilecopy_vpath == NULL)
return;
g_return_if_fail (filename != NULL);
g_return_if_fail (lc_data != NULL);
vpath = vfs_path_from_str (filename);
/* Avoid making a local copy if we are doing a cd */
do_local_copy = vfs_file_is_local (vpath) ? 0 : 1;
/*
* All commands should be run in /bin/sh regardless of user shell.
* To do that, create temporary shell script and run it.
* Sometimes it's not needed (e.g. for %cd and %view commands),
* but it's easier to create it anyway.
*/
cmd_file_fd = mc_mkstemps (&file_name_vpath, "mcext", SCRIPT_SUFFIX);
if (cmd_file_fd == -1)
if (has_changed)
{
message (D_ERROR, MSG_ERROR,
_("Cannot create temporary command file\n%s"), unix_error_string (errno));
goto ret;
struct stat mystat;
mc_stat (localfilecopy_vpath, &mystat);
has_changed = localmtime != mystat.st_mtime;
}
mc_ungetlocalcopy (filename_vpath, localfilecopy_vpath, has_changed);
vfs_path_free (localfilecopy_vpath);
localfilecopy_vpath = NULL;
}
/* --------------------------------------------------------------------------------------------- */
static char *
exec_get_file_name (gboolean do_local_copy, vfs_path_t * filename_vpath)
{
if (!do_local_copy)
return quote_func (vfs_path_get_last_path_str (filename_vpath), 0);
if (localfilecopy_vpath == NULL)
{
struct stat mystat;
localfilecopy_vpath = mc_getlocalcopy (filename_vpath);
if (localfilecopy_vpath == NULL)
return NULL;
mc_stat (localfilecopy_vpath, &mystat);
localmtime = mystat.st_mtime;
}
cmd_file = fdopen (cmd_file_fd, "w");
fputs ("#! /bin/sh\n", cmd_file);
return quote_func (vfs_path_get_last_path_str (localfilecopy_vpath), 0);
}
/* --------------------------------------------------------------------------------------------- */
static char *
exec_make_shell_string (const char *lc_data, vfs_path_t * filename_vpath)
{
GString *shell_string = g_string_new ("");
char lc_prompt[80];
gboolean parameter_found = FALSE;
gboolean expand_prefix_found = FALSE;
gboolean do_local_copy;
/* Avoid making a local copy if we are doing a cd */
do_local_copy = !vfs_file_is_local (filename_vpath);
lc_prompt[0] = '\0';
for (; *lc_data != '\0' && *lc_data != '\n'; lc_data++)
{
if (parameter_found)
@ -148,22 +162,17 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
{
char *parameter;
parameter_found = 0;
parameter_found = FALSE;
parameter = input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_EXT_PARAMETER, "");
if (parameter == NULL)
{
/* User canceled */
fclose (cmd_file);
mc_unlink (file_name_vpath);
if (localcopy_vpath != NULL)
{
mc_ungetlocalcopy (vpath, localcopy_vpath, FALSE);
vfs_path_free (localcopy_vpath);
}
goto ret;
g_string_free (shell_string, TRUE);
exec_cleanup_file_name (filename_vpath, FALSE);
return NULL;
}
fputs (parameter, cmd_file);
written_nonspace = 1;
g_string_append (shell_string, parameter);
written_nonspace = TRUE;
g_free (parameter);
}
else
@ -179,9 +188,9 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
}
else if (expand_prefix_found)
{
expand_prefix_found = 0;
expand_prefix_found = FALSE;
if (*lc_data == '{')
parameter_found = 1;
parameter_found = TRUE;
else
{
int i;
@ -191,17 +200,18 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
if (i != 0)
{
lc_data += i - 1;
run_view = 1;
run_view = TRUE;
}
else
{
i = check_format_cd (lc_data);
if (i > 0)
{
is_cd = 1;
is_cd = TRUE;
quote_func = fake_name_quote;
do_local_copy = 0;
p = buffer;
do_local_copy = FALSE;
pbuffer = buffer;
lc_data += i - 1;
}
else
@ -209,7 +219,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
i = check_format_var (lc_data, &v);
if (i > 0 && v != NULL)
{
fputs (v, cmd_file);
g_string_append (shell_string, v);
g_free (v);
lc_data += i;
}
@ -221,57 +231,172 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
text = expand_format (NULL, *lc_data, !is_cd);
else
{
if (do_local_copy)
text = exec_get_file_name (do_local_copy, filename_vpath);
if (text == NULL)
{
localcopy_vpath = mc_getlocalcopy (vpath);
if (localcopy_vpath == NULL)
{
fclose (cmd_file);
mc_unlink (file_name_vpath);
goto ret;
}
mc_stat (localcopy_vpath, &mystat);
localmtime = mystat.st_mtime;
text =
quote_func (vfs_path_get_last_path_str (localcopy_vpath),
0);
}
else
{
const vfs_path_element_t *path_element;
path_element = vfs_path_get_by_index (vpath, -1);
text = quote_func (path_element->path, 0);
g_string_free (shell_string, TRUE);
return NULL;
}
}
if (!is_cd)
fputs (text, cmd_file);
g_string_append (shell_string, text);
else
{
strcpy (p, text);
p = strchr (p, 0);
strcpy (pbuffer, text);
pbuffer = strchr (pbuffer, 0);
}
g_free (text);
written_nonspace = 1;
written_nonspace = TRUE;
}
}
}
}
}
else if (*lc_data == '%')
expand_prefix_found = 1;
expand_prefix_found = TRUE;
else
{
if (*lc_data != ' ' && *lc_data != '\t')
written_nonspace = 1;
written_nonspace = TRUE;
if (is_cd)
*(p++) = *lc_data;
*(pbuffer++) = *lc_data;
else
fputc (*lc_data, cmd_file);
g_string_append_c (shell_string, *lc_data);
}
} /* for */
return g_string_free (shell_string, FALSE);
}
/* --------------------------------------------------------------------------------------------- */
static void
exec_extension_view (char *cmd, vfs_path_t * filename_vpath, int *move_dir, int start_line,
vfs_path_t * temp_file_name_vpath)
{
mcview_ret_t ret;
int def_hex_mode = mcview_default_hex_mode, changed_hex_mode = 0;
int def_nroff_flag = mcview_default_nroff_flag, changed_nroff_flag = 0;
mcview_altered_hex_mode = 0;
mcview_altered_nroff_flag = 0;
if (def_hex_mode != mcview_default_hex_mode)
changed_hex_mode = 1;
if (def_nroff_flag != mcview_default_nroff_flag)
changed_nroff_flag = 1;
/* If we've written whitespace only, then just load filename
* into view
*/
if (written_nonspace)
{
ret = mcview_viewer (cmd, filename_vpath, start_line);
mc_unlink (temp_file_name_vpath);
}
else
ret = mcview_viewer (NULL, filename_vpath, start_line);
if (move_dir != NULL)
switch (ret)
{
case MCVIEW_WANT_NEXT:
*move_dir = 1;
break;
case MCVIEW_WANT_PREV:
*move_dir = -1;
break;
default:
*move_dir = 0;
}
if (changed_hex_mode && !mcview_altered_hex_mode)
mcview_default_hex_mode = def_hex_mode;
if (changed_nroff_flag && !mcview_altered_nroff_flag)
mcview_default_nroff_flag = def_nroff_flag;
dialog_switch_process_pending ();
}
/* --------------------------------------------------------------------------------------------- */
static void
exec_extension_cd (void)
{
char *q;
vfs_path_t *p_vpath;
*pbuffer = '\0';
pbuffer = buffer;
/* while (*p == ' ' && *p == '\t')
* p++;
*/
/* Search last non-space character. Start search at the end in order
not to short filenames containing spaces. */
q = pbuffer + strlen (pbuffer) - 1;
while (q >= pbuffer && (*q == ' ' || *q == '\t'))
q--;
q[1] = 0;
p_vpath = vfs_path_from_str_flags (pbuffer, VPF_NO_CANON);
do_cd (p_vpath, cd_parse_command);
vfs_path_free (p_vpath);
}
/* --------------------------------------------------------------------------------------------- */
static void
exec_extension (const char *filename, const char *lc_data, int *move_dir, int start_line)
{
char *shell_string;
vfs_path_t *temp_file_name_vpath;
int cmd_file_fd;
FILE *cmd_file;
char *cmd = NULL;
vfs_path_t *filename_vpath;
g_return_if_fail (filename != NULL);
g_return_if_fail (lc_data != NULL);
pbuffer = NULL;
localmtime = 0;
quote_func = name_quote;
run_view = FALSE;
is_cd = FALSE;
written_nonspace = FALSE;
filename_vpath = vfs_path_from_str (filename);
shell_string = exec_make_shell_string (lc_data, filename_vpath);
if (shell_string == NULL)
{
vfs_path_free (filename_vpath);
return;
}
/*
* All commands should be run in /bin/sh regardless of user shell.
* To do that, create temporary shell script and run it.
* Sometimes it's not needed (e.g. for %cd and %view commands),
* but it's easier to create it anyway.
*/
cmd_file_fd = mc_mkstemps (&temp_file_name_vpath, "mcext", SCRIPT_SUFFIX);
if (cmd_file_fd == -1)
{
message (D_ERROR, MSG_ERROR,
_("Cannot create temporary command file\n%s"), unix_error_string (errno));
goto ret;
}
cmd_file = fdopen (cmd_file_fd, "w");
fputs ("#! /bin/sh\n\n", cmd_file);
fputs (shell_string, cmd_file);
g_free (shell_string);
/*
* Make the script remove itself when it finishes.
@ -282,7 +407,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
{
char *file_name;
file_name = vfs_path_to_str (file_name_vpath);
file_name = vfs_path_to_str (temp_file_name_vpath);
fprintf (cmd_file, "\n/bin/rm -f %s\n", file_name);
g_free (file_name);
}
@ -291,85 +416,26 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
if ((run_view && !written_nonspace) || is_cd)
{
mc_unlink (file_name_vpath);
vfs_path_free (file_name_vpath);
file_name_vpath = NULL;
mc_unlink (temp_file_name_vpath);
vfs_path_free (temp_file_name_vpath);
temp_file_name_vpath = NULL;
}
else
{
char *file_name;
file_name = vfs_path_to_str (file_name_vpath);
file_name = vfs_path_to_str (temp_file_name_vpath);
/* Set executable flag on the command file ... */
mc_chmod (file_name_vpath, S_IRWXU);
mc_chmod (temp_file_name_vpath, S_IRWXU);
/* ... but don't rely on it - run /bin/sh explicitly */
cmd = g_strconcat ("/bin/sh ", file_name, (char *) NULL);
g_free (file_name);
}
if (run_view)
{
mcview_ret_t ret;
mcview_altered_hex_mode = 0;
mcview_altered_nroff_flag = 0;
if (def_hex_mode != mcview_default_hex_mode)
changed_hex_mode = 1;
if (def_nroff_flag != mcview_default_nroff_flag)
changed_nroff_flag = 1;
/* If we've written whitespace only, then just load filename
* into view
*/
if (written_nonspace)
{
ret = mcview_viewer (cmd, vpath, start_line);
mc_unlink (file_name_vpath);
}
else
ret = mcview_viewer (NULL, vpath, start_line);
if (move_dir != NULL)
switch (ret)
{
case MCVIEW_WANT_NEXT:
*move_dir = 1;
break;
case MCVIEW_WANT_PREV:
*move_dir = -1;
break;
default:
*move_dir = 0;
}
if (changed_hex_mode && !mcview_altered_hex_mode)
mcview_default_hex_mode = def_hex_mode;
if (changed_nroff_flag && !mcview_altered_nroff_flag)
mcview_default_nroff_flag = def_nroff_flag;
dialog_switch_process_pending ();
}
exec_extension_view (cmd, filename_vpath, move_dir, start_line, temp_file_name_vpath);
else if (is_cd)
{
char *q;
vfs_path_t *p_vpath;
*p = 0;
p = buffer;
/* while (*p == ' ' && *p == '\t')
* p++;
*/
/* Search last non-space character. Start search at the end in order
not to short filenames containing spaces. */
q = p + strlen (p) - 1;
while (q >= p && (*q == ' ' || *q == '\t'))
q--;
q[1] = 0;
p_vpath = vfs_path_from_str_flags (p, VPF_NO_CANON);
do_cd (p_vpath, cd_parse_command);
vfs_path_free (p_vpath);
}
exec_extension_cd ();
else
{
shell_execute (cmd, EXECUTE_INTERNAL);
@ -385,15 +451,10 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
g_free (cmd);
if (localcopy_vpath != NULL)
{
mc_stat (localcopy_vpath, &mystat);
mc_ungetlocalcopy (vpath, localcopy_vpath, localmtime != mystat.st_mtime);
vfs_path_free (localcopy_vpath);
}
exec_cleanup_file_name (filename_vpath, TRUE);
ret:
vfs_path_free (file_name_vpath);
vfs_path_free (vpath);
vfs_path_free (temp_file_name_vpath);
vfs_path_free (filename_vpath);
}
/* --------------------------------------------------------------------------------------------- */
@ -512,7 +573,7 @@ regex_check_type (const vfs_path_t * filename_vpath, const char *ptr, int *have_
if (*have_type == 0)
{
vfs_path_t *localfile_vpath;
const char *realname; /* name used with "file" */
const char *realname; /* name used with "file" */
#ifdef HAVE_CHARSET
int got_encoding_data;
@ -766,14 +827,14 @@ regex_command (const vfs_path_t * filename_vpath, const char *action, int *move_
else if (!strncmp (p, "shell/", 6))
{
p += 6;
if (*p == '.' && file_len >= (size_t)(q - p))
if (*p == '.' && file_len >= (size_t) (q - p))
{
if (!strncmp (p, filename + file_len - (q - p), q - p))
found = 1;
}
else
{
if ((size_t)(q - p) == file_len && !strncmp (p, filename, q - p))
if ((size_t) (q - p) == file_len && !strncmp (p, filename, q - p))
found = 1;
}
}
@ -829,32 +890,26 @@ regex_command (const vfs_path_t * filename_vpath, const char *action, int *move_
break;
continue;
}
if (!strcmp (action, p))
if (strcmp (action, p) != 0)
*r = c;
else
{
*r = c;
for (p = r + 1; *p == ' ' || *p == '\t'; p++);
for (p = r + 1; *p == ' ' || *p == '\t'; p++)
;
/* Empty commands just stop searching
* through, they don't do anything
*
* We need to copy the filename because exec_extension
* may end up invoking update_panels thus making the
* filename parameter invalid (ie, most of the time,
* we get filename as a pointer from current_panel->dir).
*/
if (p < q)
{
char *filename_copy = g_strdup (filename);
exec_extension (filename_copy, r + 1, move_dir, view_at_line_number);
g_free (filename_copy);
exec_extension (filename, r + 1, move_dir, view_at_line_number);
ret = 1;
}
break;
}
else
*r = c;
}
}
p = q;