diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2005-03-12 19:20:56 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2005-03-12 19:20:56 +0000 |
commit | aac16ff30dfecaa2f0a4e8b8cedde8a2dcc2fd44 (patch) | |
tree | b3338b11ed89f6a9ad305566697d1c80384489de /mimeview | |
parent | f11dae8ecca12b5b923f6e68eb0ee0bd564eed45 (diff) | |
download | mailutils-aac16ff30dfecaa2f0a4e8b8cedde8a2dcc2fd44.tar.gz mailutils-aac16ff30dfecaa2f0a4e8b8cedde8a2dcc2fd44.tar.bz2 |
Rewritten using display_stream_mailcap.
Diffstat (limited to 'mimeview')
-rw-r--r-- | mimeview/mimeview.c | 490 |
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 |