summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-03-12 19:20:56 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-03-12 19:20:56 +0000
commitaac16ff30dfecaa2f0a4e8b8cedde8a2dcc2fd44 (patch)
treeb3338b11ed89f6a9ad305566697d1c80384489de
parentf11dae8ecca12b5b923f6e68eb0ee0bd564eed45 (diff)
downloadmailutils-aac16ff30dfecaa2f0a4e8b8cedde8a2dcc2fd44.tar.gz
mailutils-aac16ff30dfecaa2f0a4e8b8cedde8a2dcc2fd44.tar.bz2
Rewritten using display_stream_mailcap.
-rw-r--r--mimeview/mimeview.c490
1 files changed, 33 insertions, 457 deletions
diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c
index f238ac2a9..c343cdd47 100644
--- a/mimeview/mimeview.c
+++ b/mimeview/mimeview.c
@@ -25,6 +25,8 @@
#include <sys/wait.h>
const char *program_version = "mimeview (" PACKAGE_STRING ")";
+/* TRANSLATORS: Please, preserve the vertical tabulation (^K character)
+ in this message */
static char doc[] = N_("GNU mimeview -- display files, using mailcap mechanism. \
Default mime.types file is ") DEFAULT_CUPS_CONFDIR "/mime.types"
N_("\n\nDebug flags are:\n\
@@ -36,7 +38,7 @@ N_("\n\nDebug flags are:\n\
static struct argp_option options[] = {
{"no-ask", 'a', N_("TYPE-LIST"), OPTION_ARG_OPTIONAL,
- N_("Do not ask any questions before running an interpreter to view messages of given types. TYPE-LIST is a comma-separated list of MIME types. If TYPE-LIST is not given, do not ask any questions at all"), 0},
+ N_("Do not ask for confirmation before displaying files. If TYPE-LIST is given, do not ask for confirmation before displaying such files whose MIME type matches one of the patterns from TYPE-LIST"), 0},
{"no-interactive", 'h', NULL, 0,
N_("Disable interactive mode"), 0 },
{"print", 0, NULL, OPTION_ALIAS, NULL, 0 },
@@ -55,51 +57,11 @@ int debug_level; /* Debugging level set by --debug option */
static int dry_run; /* Dry run mode */
static char *metamail; /* Name of metamail program, if requested */
static char *mimetypes_config = DEFAULT_CUPS_CONFDIR;
-static list_t no_ask_list; /* List of MIME types for which no questions
+static char *no_ask_types; /* List of MIME types for which no questions
should be asked */
static int interactive = -1;
-char *mimeview_file; /* Name of the file to view */
-FILE *mimeview_fp; /* Its descriptor */
-
-/* Default mailcap path, the $HOME/.mailcap: entry is prepended to it */
-#define DEFAULT_MAILCAP \
- "/usr/local/etc/mailcap:"\
- "/usr/etc/mailcap:"\
- "/etc/mailcap:"\
- "/etc/mail/mailcap:"\
- "/usr/public/lib/mailcap"
-
-static void
-parse_typelist (const char *str)
-{
- char *tmp = xstrdup (str);
- char *p, *sp;
-
- for (p = strtok_r (tmp, ",", &sp); p; p = strtok_r (NULL, ",", &sp))
- list_append (no_ask_list, xstrdup (p));
- free (tmp);
-}
-
-static int
-match_typelist (const char *type)
-{
- int rc = 0;
-
- if (no_ask_list)
- {
- iterator_t itr;
- list_get_iterator (no_ask_list, &itr);
- for (iterator_first (itr); !rc && !iterator_is_done (itr);
- iterator_next (itr))
- {
- char *p;
- iterator_current (itr, (void**)&p);
- rc = fnmatch (p, type, FNM_CASEFOLD) == 0;
- }
- iterator_destroy (&itr);
- }
- return rc;
-}
+char *mimeview_file; /* Name of the file to view */
+FILE *mimeview_fp; /* Its descriptor */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
@@ -119,8 +81,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case 'a':
- list_create (&no_ask_list);
- parse_typelist (arg ? arg : "*");
+ no_ask_types = arg ? arg : "*";
setenv ("MM_NOASK", arg, 1); /* In case we are given --metamail option */
break;
@@ -186,7 +147,6 @@ static int
open_file (char *name)
{
struct stat st;
-
if (stat (name, &st))
{
mu_error (_("Cannot stat `%s': %s"), name, mu_strerror (errno));
@@ -214,421 +174,13 @@ close_file ()
fclose (mimeview_fp);
}
-static struct obstack expand_stack;
-
-static int
-expand_string (char **pstr, const char *filename, const char *type)
-{
- char *p;
- size_t namelen = strlen (filename);
- size_t typelen = strlen (type);
- int rc = 0;
-
- for (p = *pstr; *p; )
- {
- switch (p[0])
- {
- case '%':
- switch (p[1])
- {
- case 's':
- obstack_grow (&expand_stack, filename, namelen);
- p += 2;
- rc = 1;
- break;
-
- case 't':
- obstack_grow (&expand_stack, type, typelen);
- p += 2;
- break;
-
- case '{':
- /* Hmm, we don't have content-type field, sorry... */
- while (*p && *p != '}')
- p++;
- if (*p)
- p++;
- break;
-
- /* FIXME: Handle %F and %n */
- default:
- obstack_1grow (&expand_stack, p[0]);
- }
- break;
-
- case '\\':
- if (p[1])
- {
- obstack_1grow (&expand_stack, p[1]);
- p += 2;
- }
- else
- {
- obstack_1grow (&expand_stack, p[0]);
- p++;
- }
- break;
-
- case '"':
- if (p[1] == p[0])
- {
- obstack_1grow (&expand_stack, '%');
- p++;
- }
- else
- {
- obstack_1grow (&expand_stack, p[0]);
- p++;
- }
- break;
-
- default:
- obstack_1grow (&expand_stack, p[0]);
- p++;
- }
- }
- obstack_1grow (&expand_stack, 0);
- free (*pstr);
- *pstr = obstack_finish (&expand_stack);
- return rc;
-}
-
-static int
-confirm_action (const char *type, const char *str)
-{
- char repl[128], *p;
- int len;
-
- if (!interactive || match_typelist (type))
- return 1;
-
- printf (_("Run `%s'?"), str);
- fflush (stdout);
-
- p = fgets (repl, sizeof repl, stdin);
- if (!p)
- return 0;
- len = strlen (p);
- if (len > 0 && p[len-1] == '\n')
- p[len--] = 0;
-
- return mu_true_answer_p (p);
-}
-
-static void
-dump_mailcap_entry (mu_mailcap_entry_t entry)
-{
- char buffer[256];
- size_t i, count;
-
- mu_mailcap_entry_get_typefield (entry, buffer,
- sizeof (buffer), NULL);
- printf ("typefield: %s\n", buffer);
-
- /* view-command. */
- mu_mailcap_entry_get_viewcommand (entry, buffer,
- sizeof (buffer), NULL);
- printf ("view-command: %s\n", buffer);
-
- /* fields. */
- mu_mailcap_entry_fields_count (entry, &count);
- for (i = 1; i <= count; i++)
- {
- int status = mu_mailcap_entry_get_field (entry, i, buffer,
- sizeof (buffer), NULL);
- if (status)
- {
- mu_error (_("cannot retrieve field %lu: %s"),
- (unsigned long) i,
- mu_strerror (status));
- break;
- }
- printf ("fields[%d]: %s\n", i, buffer);
- }
- printf ("\n");
-}
-
-pid_t
-create_filter (char *cmd, int outfd, int *infd)
-{
- pid_t pid;
- int lp[2];
-
- if (infd)
- pipe (lp);
-
- pid = fork ();
- if (pid == -1)
- {
- if (infd)
- {
- close (lp[0]);
- close (lp[1]);
- }
- mu_error ("fork: %s", mu_strerror (errno));
- return -1;
- }
-
- if (pid == 0)
- {
- /* Child process */
- int argc;
- char **argv;
-
- argcv_get (cmd, "", NULL, &argc, &argv);
-
- /* Create input channel: */
- if (lp[0] != 0)
- dup2 (lp[0], 0);
- close (lp[1]);
-
- /* Create output channel */
- if (outfd != -1 && outfd != 1)
- dup2 (outfd, 1);
-
- execvp (argv[0], argv);
- mu_error (_("Cannot execute `%s': %s"), cmd, mu_strerror (errno));
- _exit (127);
- }
-
- /* Master process */
- if (infd)
- {
- *infd = lp[1];
- close (lp[0]);
- }
- return pid;
-}
-
void
-print_exit_status (int status)
-{
- if (WIFEXITED (status))
- printf (_("Command exited with status %d\n"), WEXITSTATUS(status));
- else if (WIFSIGNALED (status))
- printf(_("Command terminated on signal %d\n"), WTERMSIG(status));
- else
- printf (_("Command terminated"));
-}
-
-static char *
-get_pager ()
-{
- char *pager = getenv ("MIMEVIEW_PAGER");
- if (!pager)
- {
- pager = getenv ("METAMAIL_PAGER");
- if (!pager)
- {
- pager = getenv ("PAGER");
- if (!pager)
- pager = "more";
- }
- }
- return pager;
-}
-
-static int
-run_test (mu_mailcap_entry_t entry, const char *type)
-{
- size_t size;
- int status = 0;
-
- if (mu_mailcap_entry_get_test (entry, NULL, 0, &size) == 0)
- {
- int argc;
- char **argv;
- char *str = xmalloc (size + 1);
- mu_mailcap_entry_get_test (entry, str, size + 1, NULL);
-
- expand_string (&str, mimeview_file, type);
- argcv_get (str, "", NULL, &argc, &argv);
- free (str);
-
- if (mu_spawnvp (argv[0], argv, &status))
- status = 1;
- argcv_free (argc, argv);
- }
- return status;
-}
-
-int
-run_mailcap (mu_mailcap_entry_t entry, const char *type)
-{
- char *view_command;
- size_t size;
- int flag;
- int status;
- int fd;
- int *pfd = NULL;
- int outfd = -1;
- pid_t pid, pager_pid;
-
- if (debug_level > 1)
- dump_mailcap_entry (entry);
-
- if (run_test (entry, type))
- return -1;
-
- if (interactive)
- {
- mu_mailcap_entry_get_viewcommand (entry, NULL, 0, &size);
- size++;
- view_command = xmalloc (size);
- mu_mailcap_entry_get_viewcommand (entry, view_command, size, NULL);
- }
- else
- {
- if (mu_mailcap_entry_get_value (entry, "print", NULL, 0, &size))
- return 1;
- size++;
- view_command = xmalloc (size);
- mu_mailcap_entry_get_value (entry, "print", view_command, size, NULL);
- }
-
- /* NOTE: We don't create temporary file for %s, we just use
- mimeview_file instead */
- if (expand_string (&view_command, mimeview_file, type))
- pfd = NULL;
- else
- pfd = &fd;
- DEBUG (0, (_("Executing %s...\n"), view_command));
-
- if (dry_run || !confirm_action (type, view_command))
- {
- free (view_command);
- return 1;
- }
-
- flag = 0;
- if (interactive
- && mu_mailcap_entry_copiousoutput (entry, &flag) == 0 && flag)
- pager_pid = create_filter (get_pager (), -1, &outfd);
-
- pid = create_filter (view_command, outfd, pfd);
- if (pid > 0)
- {
- if (pfd)
- {
- char buf[512];
- size_t n;
-
- fseek (mimeview_fp, 0, SEEK_SET);
- while ((n = fread (buf, 1, sizeof buf, mimeview_fp)) > 0)
- {
- write (fd, buf, n);
- }
- close (fd);
- }
-
- while (waitpid (pid, &status, 0) < 0)
- if (errno != EINTR)
- {
- mu_error ("waitpid: %s", mu_strerror (errno));
- break;
- }
- if (debug_level)
- print_exit_status (status);
- }
- free (view_command);
- return 0;
-}
-
-static int
-find_entry (const char *file, const char *type)
+display_file (const char *type)
{
- mu_mailcap_t mailcap;
int status;
- stream_t stream;
- int rc = 1;
-
- DEBUG (2, (_("Trying %s...\n"), file));
- status = file_stream_create (&stream, file, MU_STREAM_READ);
- if (status)
- {
- mu_error ("cannot create file stream %s: %s",
- file, mu_strerror (status));
- return -1;
- }
-
- status = stream_open (stream);
- if (status)
- {
- stream_destroy (&stream, stream_get_owner (stream));
- if (status != ENOENT)
- mu_error ("cannot open file stream %s: %s",
- file, mu_strerror (status));
- return -1;
- }
-
- status = mu_mailcap_create (&mailcap, stream);
- if (status == 0)
- {
- size_t i, count = 0;
-
- mu_mailcap_entries_count (mailcap, &count);
- for (i = 1; i <= count; i++)
- {
- mu_mailcap_entry_t entry;
- char buffer[256];
-
- if (mu_mailcap_get_entry (mailcap, i, &entry))
- continue;
-
- /* typefield. */
- mu_mailcap_entry_get_typefield (entry,
- buffer, sizeof (buffer), NULL);
-
- if (fnmatch (buffer, type, FNM_CASEFOLD) == 0)
- {
- DEBUG (2, (_("Found in %s\n"), file));
- if (run_mailcap (entry, type) == 0)
- {
- rc = 0;
- break;
- }
- }
- }
- mu_mailcap_destroy (&mailcap);
- }
- else
- {
- mu_error ("cannot create mailcap for %s: %s",
- file, mu_strerror (status));
- }
- return rc;
-}
-
-void
-display_file_mailcap (const char *type)
-{
- char *p, *sp;
- char *mailcap_path;
- mailcap_path = getenv ("MAILCAP");
- if (!mailcap_path)
- {
- char *home = mu_get_homedir ();
- asprintf (&mailcap_path, "%s/.mailcap:%s", home, DEFAULT_MAILCAP);
- }
- else
- mailcap_path = strdup (mailcap_path);
-
- obstack_init (&expand_stack);
-
- for (p = strtok_r (mailcap_path, ":", &sp); p; p = strtok_r (NULL, ":", &sp))
- {
- if (find_entry (p, type) == 0)
- break;
- }
-}
-
-void
-display_file (const char *type)
-{
if (metamail)
{
- int status;
const char *argv[7];
argv[0] = "metamail";
@@ -653,7 +205,31 @@ display_file (const char *type)
mu_spawnvp (metamail, argv, &status);
}
else
- display_file_mailcap (type);
+ {
+ stream_t stream;
+ header_t hdr;
+ char *text;
+
+ asprintf (&text, "Content-Type: %s\n", type);
+ status = header_create (&hdr, text, strlen (text), NULL);
+ if (status)
+ mu_error (_("Cannot create header: %s"), mu_strerror (status));
+ else
+ {
+ stdio_stream_create (&stream, mimeview_fp,
+ MU_STREAM_READ|MU_STREAM_SEEKABLE|MU_STREAM_NO_CLOSE);
+ stream_open (stream);
+
+ display_stream_mailcap (mimeview_file, stream, hdr,
+ no_ask_types, interactive, dry_run,
+ debug_level);
+
+ stream_close (stream);
+ stream_destroy (&stream, stream_get_owner (stream));
+
+ header_destroy (&hdr, header_get_owner (hdr));
+ }
+ }
}
int

Return to:

Send suggestions and report system problems to the System administrator.