/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999, 2001, 2005, 2007, 2009, 2010 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Mailutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ #include "mail.h" static void expand_bang (char **pbuf) { char *last = NULL; char *tmp, *p, *q; size_t count = 0; mailvar_get (&last, "gnu-last-command", mailvar_type_string, 0); for (p = *pbuf; *p; p++) if (*p == '!') count++; if (count == 0) return; if (!last) { mu_error (_("No previous command")); return; } tmp = xmalloc (strlen (*pbuf) + count * (strlen (last) - 1) + 1); for (p = *pbuf, q = tmp; *p; ) { if (*p == '!') { strcpy (q, last); q += strlen (q); p++; } else *p++ = *q++; } *q = 0; free (*pbuf); *pbuf = tmp; } int mail_execute (int shell, int argc, char **argv) { int xargc, i, status, rc; char **xargv; char *buf; if (argc == 0) { /* No arguments mean execute a copy of the user shell */ shell = 1; } xargc = argc; if (shell && argc < 3) xargc = 3; xargv = xcalloc (xargc + 1, sizeof (xargv[0])); for (i = 0; i < argc; i++) xargv[i] = argv[i]; /* Expand arguments if required */ if (mailvar_get (NULL, "bang", mailvar_type_boolean, 0) == 0) { int i; for (i = 0; i < xargc; i++) expand_bang (xargv + i); } /* Reconstruct the command line and save it to gnu-last-command variable. Important: use argc (not xargc)! */ mu_argcv_string (argc, xargv, &buf); mailvar_set ("gnu-last-command", buf, mailvar_type_string, MOPTF_QUIET | MOPTF_OVERWRITE); if (shell) { xargv[0] = getenv ("SHELL"); if (argc == 0) xargv[1] = NULL; else { xargv[1] = "-c"; xargv[2] = buf; xargv[3] = NULL; } } rc = mu_spawnvp (xargv[0], xargv, &status); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_spawnvp", xargv[0], rc); } /* FIXME: else if (status) mu_diag_output (MU_DIAG_NOTICE, .... */ free (buf); free (xargv); return rc; } /* * sh[ell] [command] -- GNU extension * ![command] -- GNU extension */ int mail_shell (int argc, char **argv) { if (argv[0][0] == '!' && strlen (argv[0]) > 1) { argv[0][0] = ' '; return mail_execute (1, argc, argv); } else if (argc > 1) { return mail_execute (0, argc-1, argv+1); } else { return mail_execute (1, 0, NULL); } return 1; }