Commit d3269a42 d3269a42e81d5df9aadae7b5cdf2e69d7dc0efc0 by Sergey Poznyakoff

mail: fix the "shell" ("!") command.

* mail/mail.h (mail_execute): Change signature. All callers updated.
* mail/shell.c (expand_bang): Change signature.  Take the
string to be expanded as the 2nd and the last command as 3rd arguments.
Always allocate the return string, even if there's nothing to expand.
(mail_execute): fix memory management.
* mail/escape.c: Update.
* mail/escape.c: Update calls to mail_execute.
1 parent 6bd92d3c
...@@ -173,7 +173,7 @@ escape_check_args (int argc, char **argv) ...@@ -173,7 +173,7 @@ escape_check_args (int argc, char **argv)
173 int 173 int
174 escape_shell (int argc, char **argv, compose_env_t *env) 174 escape_shell (int argc, char **argv, compose_env_t *env)
175 { 175 {
176 return mail_execute (1, argc - 1, argv + 1); 176 return mail_execute (1, argv[1], argc - 1, argv + 1);
177 } 177 }
178 178
179 /* ~:[mail-command] */ 179 /* ~:[mail-command] */
...@@ -325,7 +325,7 @@ run_editor (char *ed, char *arg) ...@@ -325,7 +325,7 @@ run_editor (char *ed, char *arg)
325 argv[0] = ed; 325 argv[0] = ed;
326 argv[1] = arg; 326 argv[1] = arg;
327 argv[2] = NULL; 327 argv[2] = NULL;
328 return mail_execute (1, 2, argv); 328 return mail_execute (1, arg, 2, argv);
329 } 329 }
330 330
331 static int 331 static int
......
...@@ -217,7 +217,7 @@ extern int mail_save (int argc, char **argv); ...@@ -217,7 +217,7 @@ extern int mail_save (int argc, char **argv);
217 extern int mail_sendheader (int argc, char **argv); 217 extern int mail_sendheader (int argc, char **argv);
218 extern int mail_set (int argc, char **argv); 218 extern int mail_set (int argc, char **argv);
219 extern int mail_shell (int argc, char **argv); 219 extern int mail_shell (int argc, char **argv);
220 extern int mail_execute (int shell, int argc, char **argv); 220 extern int mail_execute (int shell, char *progname, int argc, char **argv);
221 extern int mail_size (int argc, char **argv); 221 extern int mail_size (int argc, char **argv);
222 extern int mail_source (int argc, char **argv); 222 extern int mail_source (int argc, char **argv);
223 extern int mail_summary (int argc, char **argv); 223 extern int mail_summary (int argc, char **argv);
......
...@@ -18,20 +18,21 @@ ...@@ -18,20 +18,21 @@
18 #include "mail.h" 18 #include "mail.h"
19 19
20 static void 20 static void
21 expand_bang (char **pbuf) 21 expand_bang (char **pbuf, const char *arg, const char *last)
22 { 22 {
23 char *last = NULL; 23 char *tmp, *q;
24 char *tmp, *p, *q; 24 const char *p;
25 size_t count = 0; 25 size_t count = 0;
26 26
27 mailvar_get (&last, "gnu-last-command", mailvar_type_string, 0); 27 for (p = arg; *p; p++)
28
29 for (p = *pbuf; *p; p++)
30 if (*p == '!') 28 if (*p == '!')
31 count++; 29 count++;
32 30
33 if (count == 0) 31 if (count == 0)
34 return; 32 {
33 *pbuf = xstrdup (arg);
34 return;
35 }
35 36
36 if (!last) 37 if (!last)
37 { 38 {
...@@ -39,8 +40,8 @@ expand_bang (char **pbuf) ...@@ -39,8 +40,8 @@ expand_bang (char **pbuf)
39 return; 40 return;
40 } 41 }
41 42
42 tmp = xmalloc (strlen (*pbuf) + count * (strlen (last) - 1) + 1); 43 tmp = xmalloc (strlen (arg) + count * (strlen (last) - 1) + 1);
43 for (p = *pbuf, q = tmp; *p; ) 44 for (p = arg, q = tmp; *p; )
44 { 45 {
45 if (*p == '!') 46 if (*p == '!')
46 { 47 {
...@@ -49,7 +50,7 @@ expand_bang (char **pbuf) ...@@ -49,7 +50,7 @@ expand_bang (char **pbuf)
49 p++; 50 p++;
50 } 51 }
51 else 52 else
52 *p++ = *q++; 53 *q++ = *p++;
53 } 54 }
54 *q = 0; 55 *q = 0;
55 56
...@@ -58,12 +59,13 @@ expand_bang (char **pbuf) ...@@ -58,12 +59,13 @@ expand_bang (char **pbuf)
58 } 59 }
59 60
60 int 61 int
61 mail_execute (int shell, int argc, char **argv) 62 mail_execute (int shell, char *progname, int argc, char **argv)
62 { 63 {
63 int xargc, i, status, rc; 64 int xargc, i, status, rc;
64 char **xargv; 65 char **xargv;
65 char *buf; 66 char *buf;
66 67 int expanded; /* Indicates whether argv has been bang-expanded */
68
67 if (argc == 0) 69 if (argc == 0)
68 { 70 {
69 /* No arguments mean execute a copy of the user shell */ 71 /* No arguments mean execute a copy of the user shell */
...@@ -75,18 +77,27 @@ mail_execute (int shell, int argc, char **argv) ...@@ -75,18 +77,27 @@ mail_execute (int shell, int argc, char **argv)
75 xargc = 3; 77 xargc = 3;
76 xargv = xcalloc (xargc + 1, sizeof (xargv[0])); 78 xargv = xcalloc (xargc + 1, sizeof (xargv[0]));
77 79
78 for (i = 0; i < argc; i++)
79 xargv[i] = argv[i];
80
81 /* Expand arguments if required */ 80 /* Expand arguments if required */
82 if (mailvar_get (NULL, "bang", mailvar_type_boolean, 0) == 0) 81 if (mailvar_get (NULL, "bang", mailvar_type_boolean, 0) == 0)
83 { 82 {
84 int i; 83 int i;
85 84 char *last = NULL;
86 for (i = 0; i < xargc; i++) 85
87 expand_bang (xargv + i); 86 mailvar_get (&last, "gnu-last-command", mailvar_type_string, 0);
87 expand_bang (xargv, progname, last);
88 for (i = 1; i < argc; i++)
89 expand_bang (xargv + i, argv[i], last);
90 expanded = 1;
88 } 91 }
89 92 else
93 {
94 if (argc)
95 xargv[0] = progname;
96 for (i = 1; i < argc; i++)
97 xargv[i] = argv[i];
98 expanded = 0;
99 }
100
90 /* Reconstruct the command line and save it to gnu-last-command variable. 101 /* Reconstruct the command line and save it to gnu-last-command variable.
91 Important: use argc (not xargc)! 102 Important: use argc (not xargc)!
92 */ 103 */
...@@ -96,14 +107,25 @@ mail_execute (int shell, int argc, char **argv) ...@@ -96,14 +107,25 @@ mail_execute (int shell, int argc, char **argv)
96 107
97 if (shell) 108 if (shell)
98 { 109 {
110 if (expanded)
111 {
112 for (i = 0; i < argc; i++)
113 free (xargv[i]);
114 expanded = 0;
115 }
116
99 xargv[0] = getenv ("SHELL"); 117 xargv[0] = getenv ("SHELL");
100 if (argc == 0) 118 if (argc == 0)
101 xargv[1] = NULL; 119 {
120 xargv[1] = NULL;
121 xargc = 1;
122 }
102 else 123 else
103 { 124 {
104 xargv[1] = "-c"; 125 xargv[1] = "-c";
105 xargv[2] = buf; 126 xargv[2] = buf;
106 xargv[3] = NULL; 127 xargv[3] = NULL;
128 xargc = 3;
107 } 129 }
108 } 130 }
109 131
...@@ -117,6 +139,9 @@ mail_execute (int shell, int argc, char **argv) ...@@ -117,6 +139,9 @@ mail_execute (int shell, int argc, char **argv)
117 mu_diag_output (MU_DIAG_NOTICE, .... 139 mu_diag_output (MU_DIAG_NOTICE, ....
118 */ 140 */
119 free (buf); 141 free (buf);
142 if (expanded)
143 for (i = 0; i < argc; i++)
144 free (xargv[i]);
120 free (xargv); 145 free (xargv);
121 return rc; 146 return rc;
122 } 147 }
...@@ -130,18 +155,11 @@ int ...@@ -130,18 +155,11 @@ int
130 mail_shell (int argc, char **argv) 155 mail_shell (int argc, char **argv)
131 { 156 {
132 if (argv[0][0] == '!' && strlen (argv[0]) > 1) 157 if (argv[0][0] == '!' && strlen (argv[0]) > 1)
133 { 158 return mail_execute (1, argv[0] + 1, argc, argv);
134 argv[0][0] = ' ';
135 return mail_execute (1, argc, argv);
136 }
137 else if (argc > 1) 159 else if (argc > 1)
138 { 160 return mail_execute (0, argv[1], argc-1, argv+1);
139 return mail_execute (0, argc-1, argv+1);
140 }
141 else 161 else
142 { 162 return mail_execute (1, NULL, 0, NULL);
143 return mail_execute (1, 0, NULL);
144 }
145 return 1; 163 return 1;
146 } 164 }
147 165
......