Patch to eliminate temporary scripts in the exec_extention()
Andrew V. Samoilov
sav at bcs.zp.ua
Tue Nov 5 15:38:23 UTC 2002
Hello,
this patch eliminates temporary scripts in exec_extension().
Command are written to g_malloc()ed string instead of temporary
file and executed directly by subshell or passed to popen().
Weak areas for this solution:
1) Shell specific syntax (None noted in the mc.ext.in).
2) Possibility to pollute or change environment if subshell support
is used (points of view differs).
3) exit, return or exec stop subshell execution (None noted in the mc.ext).
Best regards,
Andrew V. Samoilov.
--- mc/src/ext.c Thu Oct 31 12:33:59 2002
+++ mc/src/ext.c Tue Nov 5 16:21:39 2002
@@ -57,7 +57,37 @@ flush_extension_file (void)
g_free (data);
data = NULL;
}
+}
+/*
+ * growing_string (buf, buf_size, step, hw_mark, text, text_size)
+ *
+ * Appends first TEXT_SIZE characters of TEXT to the g_malloc()ed BUF
+ * initially filled up to HW_MARK starting from &BUF[HW_MARK].
+ * BUF is g_realloc()ed if BUF_SIZE cannot fit resulting string.
+ * Increase step equals to STEP.
+ *
+ * Returns:
+ * BUF (possible g_realloc()ated.)
+ * BUF_SIZE initial BUF size.
+ * HW_MARK last filled byte in BUF
+ *
+ */
+static char *
+growing_string (char *buf, int *buf_size, int step, int *hw_mark,
+ const char *text, int text_size)
+{
+ int new_size = *buf_size;
+ while (*hw_mark + text_size >= new_size - 1)
+ new_size += step;
+ if (new_size != *buf_size)
+ buf = g_realloc (buf, new_size);
+ if (!buf)
+ return 0;
+ *buf_size = new_size;
+ memcpy (&buf[*hw_mark], text, text_size);
+ *hw_mark += text_size;
+ return buf;
}
typedef char *(*quote_func_t) (const char *name, int i);
@@ -66,10 +89,9 @@ 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 cmd_size = 0;
+ int cmd_hw_mark = 0;
int expand_prefix_found = 0;
int parameter_found = 0;
char prompt[80];
@@ -95,23 +117,6 @@ exec_extension (const char *filename, co
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) {
@@ -121,15 +126,14 @@ exec_extension (const char *filename, co
parameter = input_dialog (_(" Parameter "), prompt, "");
if (!parameter) {
/* User canceled */
- fclose (cmd_file);
- unlink (file_name);
if (localcopy) {
mc_ungetlocalcopy (filename, localcopy, 0);
}
- g_free (file_name);
+ g_free (cmd);
return;
}
- fputs (parameter, cmd_file);
+ cmd = growing_string (cmd, &cmd_size, 80, &cmd_hw_mark,
+ parameter, strlen (parameter));
written_nonspace = 1;
g_free (parameter);
} else {
@@ -158,7 +162,8 @@ exec_extension (const char *filename, co
p = buffer;
data += i - 1;
} else if ((i = check_format_var (data, &v)) > 0 && v) {
- fputs (v, cmd_file);
+ cmd = growing_string (cmd, &cmd_size, 80, &cmd_hw_mark,
+ v, strlen (v));
g_free (v);
data += i;
} else {
@@ -168,9 +173,7 @@ exec_extension (const char *filename, co
if (do_local_copy) {
localcopy = mc_getlocalcopy (filename);
if (localcopy == NULL) {
- fclose (cmd_file);
- unlink (file_name);
- g_free (file_name);
+ g_free (cmd);
return;
}
mc_stat (localcopy, &mystat);
@@ -182,7 +185,8 @@ exec_extension (const char *filename, co
} else
text = expand_format (NULL, *data, !is_cd);
if (!is_cd)
- fputs (text, cmd_file);
+ cmd = growing_string (cmd, &cmd_size, 80, &cmd_hw_mark,
+ text, strlen (text));
else {
strcpy (p, text);
p = strchr (p, 0);
@@ -200,36 +204,19 @@ exec_extension (const char *filename, co
if (is_cd)
*(p++) = *data;
else
- fputc (*data, cmd_file);
+ cmd = growing_string (cmd, &cmd_size, 80, &cmd_hw_mark,
+ data, 1);
}
}
} /* 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 {
- int cmd_len = strlen (file_name) + 10;
-
- /* Set executable flag on the command file ... */
- chmod (file_name, S_IRWXU);
- /* ... but don't rely on it - run /bin/sh explicitly */
- cmd = g_malloc (cmd_len);
- g_snprintf (cmd, cmd_len, "/bin/sh %s", file_name);
+ g_free (cmd);
+ cmd = NULL;
+ } else if (cmd) {
+ /* Add trailing zero */
+ cmd = growing_string (cmd, &cmd_size, 1, &cmd_hw_mark, "", 1);
}
-
if (run_view) {
altered_hex_mode = 0;
altered_nroff_flag = 0;
@@ -238,33 +224,26 @@ exec_extension (const char *filename, co
if (def_nroff_flag != default_nroff_flag)
changed_nroff_flag = 1;
- /* If we've written whitespace only, then just load filename
+ /* If we've written whitespace(s) 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);
- }
+ view (cmd, 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;
+ /* Search last non-space character. Start search at the end in order
+ not to short filenames containing spaces. */
+ *p-- = 0;
+ while (p >= buffer && (*p == ' ' || *p == '\t'))
+ p--;
+ p[1] = 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);
@@ -275,12 +254,10 @@ exec_extension (const char *filename, co
LINES - keybar_visible -
output_lines - 1,
LINES - keybar_visible - 1);
-
}
}
}
- g_free (file_name);
g_free (cmd);
if (localcopy) {
@@ -472,7 +449,7 @@ regex_check_type (char *filename, int fi
* if the value for %d exists, then the viewer is started up at that line number.
*/
int
-regex_command (char *filename, char *action, int *move_dir)
+regex_command (char *filename, const char *action, int *move_dir)
{
char *p, *q, *r, c;
int file_len = strlen (filename);
@@ -489,7 +466,7 @@ regex_command (char *filename, char *act
/* Check for the special View:%d parameter */
if (strncmp (action, "View:", 5) == 0) {
view_at_line_number = atoi (action + 5);
- action[4] = 0;
+ action = "View";
} else {
view_at_line_number = 0;
}
--- mc/src/ext.h Wed Sep 11 09:38:47 2002
+++ mc/src/ext.h Tue Nov 5 14:03:22 2002
@@ -1,7 +1,7 @@
#ifndef __EXT_H
#define __EXT_H
-int regex_command (char *filename, char *action, int *move_dir);
+int regex_command (char *filename, const char *action, int *move_dir);
/* Call it after the user has edited the mc.ext file,
* to flush the cached mc.ext file
--- mc/src/screen.c Thu Oct 31 12:34:43 2002
+++ mc/src/screen.c Tue Nov 5 16:47:46 2002
@@ -34,7 +34,7 @@
#include "tree.h"
#include "win.h"
#include "main.h"
-#include "ext.h" /* regexp_command */
+#include "ext.h" /* regex_command() */
#include "mouse.h" /* For Gpm_Event */
#include "layout.h" /* Most layout variables are here */
#include "dialog.h" /* for message (...) */
More information about the mc-devel
mailing list