Пример #1
0
static void
exec_extension (const char *filename, const char *data, int *move_dir,
		int start_line)
{
    char *file_name;
    int cmd_file_fd;
    FILE *cmd_file;
    char *cmd = NULL;
    int expand_prefix_found = 0;
    int parameter_found = 0;
    char prompt[80];
    int run_view = 0;
    int def_hex_mode = default_hex_mode, changed_hex_mode = 0;
    int def_nroff_flag = default_nroff_flag, changed_nroff_flag = 0;
    int written_nonspace = 0;
    int is_cd = 0;
    char buffer[1024];
    char *p = 0;
    char *localcopy = NULL;
    int do_local_copy;
    time_t localmtime = 0;
    struct stat mystat;
    quote_func_t quote_func = name_quote;

    g_return_if_fail (filename != NULL);
    g_return_if_fail (data != NULL);

    /* Avoid making a local copy if we are doing a cd */
    if (!vfs_file_is_local (filename))
	do_local_copy = 1;
    else
	do_local_copy = 0;

    /*
     * 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, "mcext", SCRIPT_SUFFIX);

    if (cmd_file_fd == -1) {
	message (1, MSG_ERROR,
		 _(" Cannot create temporary command file \n %s "),
		 unix_error_string (errno));
	return;
    }
    cmd_file = fdopen (cmd_file_fd, "w");
    fputs ("#! /bin/sh\n", cmd_file);

    prompt[0] = 0;
    for (; *data && *data != '\n'; data++) {
	if (parameter_found) {
	    if (*data == '}') {
		char *parameter;
		parameter_found = 0;
		parameter = input_dialog (_(" Parameter "), prompt, "");
		if (!parameter) {
		    /* User canceled */
		    fclose (cmd_file);
		    unlink (file_name);
		    if (localcopy) {
			mc_ungetlocalcopy (filename, localcopy, 0);
			g_free (localcopy);
		    }
		    g_free (file_name);
		    return;
		}
		fputs (parameter, cmd_file);
		written_nonspace = 1;
		g_free (parameter);
	    } else {
		size_t len = strlen (prompt);

		if (len < sizeof (prompt) - 1) {
		    prompt[len] = *data;
		    prompt[len + 1] = 0;
		}
	    }
	} else if (expand_prefix_found) {
	    expand_prefix_found = 0;
	    if (*data == '{')
		parameter_found = 1;
	    else {
		int i = check_format_view (data);
		char *v;

		if (i) {
		    data += i - 1;
		    run_view = 1;
		} else if ((i = check_format_cd (data)) > 0) {
		    is_cd = 1;
		    quote_func = fake_name_quote;
		    do_local_copy = 0;
		    p = buffer;
		    data += i - 1;
		} else if ((i = check_format_var (data, &v)) > 0 && v) {
		    fputs (v, cmd_file);
		    g_free (v);
		    data += i;
		} else {
		    char *text;

		    if (*data == 'f') {
			if (do_local_copy) {
			    localcopy = mc_getlocalcopy (filename);
			    if (localcopy == NULL) {
				fclose (cmd_file);
				unlink (file_name);
				g_free (file_name);
				return;
			    }
			    mc_stat (localcopy, &mystat);
			    localmtime = mystat.st_mtime;
			    text = (*quote_func) (localcopy, 0);
			} else {
			    text = (*quote_func) (filename, 0);
			}
		    } else
			text = expand_format (NULL, *data, !is_cd);
		    if (!is_cd)
			fputs (text, cmd_file);
		    else {
			strcpy (p, text);
			p = strchr (p, 0);
		    }
		    g_free (text);
		    written_nonspace = 1;
		}
	    }
	} else {
	    if (*data == '%')
		expand_prefix_found = 1;
	    else {
		if (*data != ' ' && *data != '\t')
		    written_nonspace = 1;
		if (is_cd)
		    *(p++) = *data;
		else
		    fputc (*data, cmd_file);
	    }
	}
    }				/* for */

    /*
     * Make the script remove itself when it finishes.
     * Don't do it for the viewer - it may need to rerun the script,
     * so we clean up after calling view().
     */
    if (!run_view) {
	fprintf (cmd_file, "\n/bin/rm -f %s\n", file_name);
    }

    fclose (cmd_file);

    if ((run_view && !written_nonspace) || is_cd) {
	unlink (file_name);
	g_free (file_name);
	file_name = NULL;
    } else {
	/* Set executable flag on the command file ... */
	chmod (file_name, S_IRWXU);
	/* ... but don't rely on it - run /bin/sh explicitly */
	cmd = g_strconcat ("/bin/sh ", file_name, (char *) NULL);
    }

    if (run_view) {
	altered_hex_mode = 0;
	altered_nroff_flag = 0;
	if (def_hex_mode != default_hex_mode)
	    changed_hex_mode = 1;
	if (def_nroff_flag != default_nroff_flag)
	    changed_nroff_flag = 1;

	/* If we've written whitespace only, then just load filename
	 * into view
	 */
	if (written_nonspace) {
	    view (cmd, filename, move_dir, start_line);
	    unlink (file_name);
	} else {
	    view (0, filename, move_dir, start_line);
	}
	if (changed_hex_mode && !altered_hex_mode)
	    default_hex_mode = def_hex_mode;
	if (changed_nroff_flag && !altered_nroff_flag)
	    default_nroff_flag = def_nroff_flag;
	repaint_screen ();
    } else if (is_cd) {
	char *q;
	*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;
	do_cd (p, cd_parse_command);
    } else {
	shell_execute (cmd, EXECUTE_INTERNAL);
	if (console_flag) {
	    handle_console (CONSOLE_SAVE);
	    if (output_lines && keybar_visible) {
		show_console_contents (output_start_y,
				       LINES - keybar_visible -
				       output_lines - 1,
				       LINES - keybar_visible - 1);

	    }
	}
    }

    g_free (file_name);
    g_free (cmd);

    if (localcopy) {
	mc_stat (localcopy, &mystat);
	mc_ungetlocalcopy (filename, localcopy,
			   localmtime != mystat.st_mtime);
	g_free (localcopy);
    }
}
Пример #2
0
Файл: ext.c Проект: inso/mc
static char *
exec_make_shell_string (const char *lc_data, const vfs_path_t * filename_vpath)
{
    GString *shell_string;
    char lc_prompt[80] = "\0";
    gboolean parameter_found = FALSE;
    gboolean expand_prefix_found = FALSE;

    shell_string = g_string_new ("");

    for (; *lc_data != '\0' && *lc_data != '\n'; lc_data++)
    {
        if (parameter_found)
        {
            if (*lc_data == '}')
            {
                char *parameter;

                parameter_found = FALSE;
                parameter =
                    input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_EXT_PARAMETER, "",
                                  INPUT_COMPLETE_NONE);
                if (parameter == NULL)
                {
                    /* User canceled */
                    g_string_free (shell_string, TRUE);
                    exec_cleanup_file_name (filename_vpath, FALSE);
                    return NULL;
                }
                g_string_append (shell_string, parameter);
                written_nonspace = TRUE;
                g_free (parameter);
            }
            else
            {
                size_t len = strlen (lc_prompt);

                if (len < sizeof (lc_prompt) - 1)
                {
                    lc_prompt[len] = *lc_data;
                    lc_prompt[len + 1] = '\0';
                }
            }
        }
        else if (expand_prefix_found)
        {
            expand_prefix_found = FALSE;
            if (*lc_data == '{')
                parameter_found = TRUE;
            else
            {
                int i;
                char *v;

                i = check_format_view (lc_data);
                if (i != 0)
                {
                    lc_data += i - 1;
                    run_view = TRUE;
                }
                else
                {
                    i = check_format_cd (lc_data);
                    if (i > 0)
                    {
                        is_cd = TRUE;
                        quote_func = fake_name_quote;
                        do_local_copy = FALSE;
                        pbuffer = buffer;
                        lc_data += i - 1;
                    }
                    else
                    {
                        i = check_format_var (lc_data, &v);
                        if (i > 0 && v != NULL)
                        {
                            g_string_append (shell_string, v);
                            g_free (v);
                            lc_data += i;
                        }
                        else
                        {
                            char *text;

                            if (*lc_data != 'f')
                                text = expand_format (NULL, *lc_data, !is_cd);
                            else
                            {
                                text = exec_get_file_name (filename_vpath);
                                if (text == NULL)
                                {
                                    g_string_free (shell_string, TRUE);
                                    return NULL;
                                }
                            }

                            if (!is_cd)
                                g_string_append (shell_string, text);
                            else
                            {
                                strcpy (pbuffer, text);
                                pbuffer = strchr (pbuffer, 0);
                            }

                            g_free (text);
                            written_nonspace = TRUE;
                        }
                    }
                }
            }
        }
        else if (*lc_data == '%')
            expand_prefix_found = TRUE;
        else
        {
            if (*lc_data != ' ' && *lc_data != '\t')
                written_nonspace = TRUE;
            if (is_cd)
                *(pbuffer++) = *lc_data;
            else
                g_string_append_c (shell_string, *lc_data);
        }
    }                           /* for */
    return g_string_free (shell_string, FALSE);
}