Handle --no-ask and --no-interactive (-h)
options. Continue search for a matching entry when necessary. Implement 'test' and 'print' commands.
Showing
1 changed file
with
186 additions
and
74 deletions
... | @@ -35,6 +35,11 @@ N_("\n\nDebug flags are:\n\ | ... | @@ -35,6 +35,11 @@ N_("\n\nDebug flags are:\n\ |
35 | #define OPT_METAMAIL 256 | 35 | #define OPT_METAMAIL 256 |
36 | 36 | ||
37 | static struct argp_option options[] = { | 37 | static struct argp_option options[] = { |
38 | {"no-ask", 'a', N_("TYPE-LIST"), OPTION_ARG_OPTIONAL, | ||
39 | 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}, | ||
40 | {"no-interactive", 'h', NULL, 0, | ||
41 | N_("Disable interactive mode"), 0 }, | ||
42 | {"print", 0, NULL, OPTION_ALIAS, NULL, 0 }, | ||
38 | {"debug", 'd', N_("FLAGS"), OPTION_ARG_OPTIONAL, | 43 | {"debug", 'd', N_("FLAGS"), OPTION_ARG_OPTIONAL, |
39 | N_("Enable debugging output"), 0}, | 44 | N_("Enable debugging output"), 0}, |
40 | {"mimetypes", 't', N_("FILE"), 0, | 45 | {"mimetypes", 't', N_("FILE"), 0, |
... | @@ -50,7 +55,9 @@ int debug_level; /* Debugging level set by --debug option */ | ... | @@ -50,7 +55,9 @@ int debug_level; /* Debugging level set by --debug option */ |
50 | static int dry_run; /* Dry run mode */ | 55 | static int dry_run; /* Dry run mode */ |
51 | static char *metamail; /* Name of metamail program, if requested */ | 56 | static char *metamail; /* Name of metamail program, if requested */ |
52 | static char *mimetypes_config = DEFAULT_CUPS_CONFDIR; | 57 | static char *mimetypes_config = DEFAULT_CUPS_CONFDIR; |
53 | 58 | static list_t no_ask_list; /* List of MIME types for which no questions | |
59 | should be asked */ | ||
60 | static int interactive = -1; | ||
54 | char *mimeview_file; /* Name of the file to view */ | 61 | char *mimeview_file; /* Name of the file to view */ |
55 | FILE *mimeview_fp; /* Its descriptor */ | 62 | FILE *mimeview_fp; /* Its descriptor */ |
56 | 63 | ||
... | @@ -62,6 +69,37 @@ FILE *mimeview_fp; /* Its descriptor */ | ... | @@ -62,6 +69,37 @@ FILE *mimeview_fp; /* Its descriptor */ |
62 | "/etc/mail/mailcap:"\ | 69 | "/etc/mail/mailcap:"\ |
63 | "/usr/public/lib/mailcap" | 70 | "/usr/public/lib/mailcap" |
64 | 71 | ||
72 | static void | ||
73 | parse_typelist (const char *str) | ||
74 | { | ||
75 | char *tmp = xstrdup (str); | ||
76 | char *p, *sp; | ||
77 | |||
78 | for (p = strtok_r (tmp, ",", &sp); p; p = strtok_r (NULL, ",", &sp)) | ||
79 | list_append (no_ask_list, xstrdup (p)); | ||
80 | free (tmp); | ||
81 | } | ||
82 | |||
83 | static int | ||
84 | match_typelist (const char *type) | ||
85 | { | ||
86 | int rc = 0; | ||
87 | |||
88 | if (no_ask_list) | ||
89 | { | ||
90 | iterator_t itr; | ||
91 | list_get_iterator (no_ask_list, &itr); | ||
92 | for (iterator_first (itr); !rc && !iterator_is_done (itr); | ||
93 | iterator_next (itr)) | ||
94 | { | ||
95 | char *p; | ||
96 | iterator_current (itr, (void**)&p); | ||
97 | rc = fnmatch (p, type, FNM_CASEFOLD) == 0; | ||
98 | } | ||
99 | iterator_destroy (&itr); | ||
100 | } | ||
101 | return rc; | ||
102 | } | ||
65 | 103 | ||
66 | static error_t | 104 | static error_t |
67 | parse_opt (int key, char *arg, struct argp_state *state) | 105 | parse_opt (int key, char *arg, struct argp_state *state) |
... | @@ -71,6 +109,8 @@ parse_opt (int key, char *arg, struct argp_state *state) | ... | @@ -71,6 +109,8 @@ parse_opt (int key, char *arg, struct argp_state *state) |
71 | case ARGP_KEY_INIT: | 109 | case ARGP_KEY_INIT: |
72 | mimetypes_lex_debug (0); | 110 | mimetypes_lex_debug (0); |
73 | mimetypes_gram_debug (0); | 111 | mimetypes_gram_debug (0); |
112 | if (interactive == -1) | ||
113 | interactive = isatty (fileno (stdin)); | ||
74 | break; | 114 | break; |
75 | 115 | ||
76 | case ARGP_KEY_FINI: | 116 | case ARGP_KEY_FINI: |
... | @@ -78,6 +118,12 @@ parse_opt (int key, char *arg, struct argp_state *state) | ... | @@ -78,6 +118,12 @@ parse_opt (int key, char *arg, struct argp_state *state) |
78 | debug_level = 1; | 118 | debug_level = 1; |
79 | break; | 119 | break; |
80 | 120 | ||
121 | case 'a': | ||
122 | list_create (&no_ask_list); | ||
123 | parse_typelist (arg ? arg : "*"); | ||
124 | setenv ("MM_NOASK", arg, 1); /* In case we are given --metamail option */ | ||
125 | break; | ||
126 | |||
81 | case 'd': | 127 | case 'd': |
82 | if (!arg) | 128 | if (!arg) |
83 | arg = "9"; | 129 | arg = "9"; |
... | @@ -99,6 +145,10 @@ parse_opt (int key, char *arg, struct argp_state *state) | ... | @@ -99,6 +145,10 @@ parse_opt (int key, char *arg, struct argp_state *state) |
99 | } | 145 | } |
100 | break; | 146 | break; |
101 | 147 | ||
148 | case 'h': | ||
149 | interactive = 0; | ||
150 | break; | ||
151 | |||
102 | case 'n': | 152 | case 'n': |
103 | dry_run = 1; | 153 | dry_run = 1; |
104 | break; | 154 | break; |
... | @@ -244,68 +294,25 @@ expand_string (char **pstr, const char *filename, const char *type) | ... | @@ -244,68 +294,25 @@ expand_string (char **pstr, const char *filename, const char *type) |
244 | } | 294 | } |
245 | 295 | ||
246 | static int | 296 | static int |
247 | find_entry (const char *file, const char *type, | 297 | confirm_action (const char *type, const char *str) |
248 | mu_mailcap_entry_t *pentry, | ||
249 | mu_mailcap_t *pmc) | ||
250 | { | 298 | { |
251 | mu_mailcap_t mailcap; | 299 | char repl[128], *p; |
252 | int status; | 300 | int len; |
253 | stream_t stream; | ||
254 | |||
255 | DEBUG (2, (_("Trying %s...\n"), file)); | ||
256 | status = file_stream_create (&stream, file, MU_STREAM_READ); | ||
257 | if (status) | ||
258 | { | ||
259 | mu_error ("cannot create file stream %s: %s", | ||
260 | file, mu_strerror (status)); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | status = stream_open (stream); | ||
265 | if (status) | ||
266 | { | ||
267 | stream_destroy (&stream, stream_get_owner (stream)); | ||
268 | if (status != ENOENT) | ||
269 | mu_error ("cannot open file stream %s: %s", | ||
270 | file, mu_strerror (status)); | ||
271 | return 0; | ||
272 | } | ||
273 | 301 | ||
274 | status = mu_mailcap_create (&mailcap, stream); | 302 | if (!interactive || match_typelist (type)) |
275 | if (status == 0) | 303 | return 1; |
276 | { | ||
277 | size_t i, count = 0; | ||
278 | |||
279 | mu_mailcap_entries_count (mailcap, &count); | ||
280 | for (i = 1; i <= count; i++) | ||
281 | { | ||
282 | mu_mailcap_entry_t entry; | ||
283 | char buffer[256]; | ||
284 | |||
285 | if (mu_mailcap_get_entry (mailcap, i, &entry)) | ||
286 | continue; | ||
287 | 304 | ||
288 | /* typefield. */ | 305 | printf (_("Run `%s'?"), str); |
289 | mu_mailcap_entry_get_typefield (entry, | 306 | fflush (stdout); |
290 | buffer, sizeof (buffer), NULL); | ||
291 | 307 | ||
292 | if (fnmatch (buffer, type, FNM_CASEFOLD) == 0) | 308 | p = fgets (repl, sizeof repl, stdin); |
293 | { | 309 | if (!p) |
294 | DEBUG (2, (_("Found in %s\n"), file)); | ||
295 | /* FIXME: Run test entry, if any */ | ||
296 | *pmc = mailcap; | ||
297 | *pentry = entry; | ||
298 | return 1; /* We leave stream open! */ | ||
299 | } | ||
300 | } | ||
301 | mu_mailcap_destroy (&mailcap); | ||
302 | } | ||
303 | else | ||
304 | { | ||
305 | mu_error ("cannot create mailcap for %s: %s", | ||
306 | file, mu_strerror (status)); | ||
307 | } | ||
308 | return 0; | 310 | return 0; |
311 | len = strlen (p); | ||
312 | if (len > 0 && p[len-1] == '\n') | ||
313 | p[len--] = 0; | ||
314 | |||
315 | return mu_true_answer_p (p); | ||
309 | } | 316 | } |
310 | 317 | ||
311 | static void | 318 | static void |
... | @@ -421,6 +428,30 @@ get_pager () | ... | @@ -421,6 +428,30 @@ get_pager () |
421 | return pager; | 428 | return pager; |
422 | } | 429 | } |
423 | 430 | ||
431 | static int | ||
432 | run_test (mu_mailcap_entry_t entry, const char *type) | ||
433 | { | ||
434 | size_t size; | ||
435 | int status = 0; | ||
436 | |||
437 | if (mu_mailcap_entry_get_test (entry, NULL, 0, &size) == 0) | ||
438 | { | ||
439 | int argc; | ||
440 | char **argv; | ||
441 | char *str = xmalloc (size + 1); | ||
442 | mu_mailcap_entry_get_test (entry, str, size + 1, NULL); | ||
443 | |||
444 | expand_string (&str, mimeview_file, type); | ||
445 | argcv_get (str, "", NULL, &argc, &argv); | ||
446 | free (str); | ||
447 | |||
448 | if (mu_spawnvp (argv[0], argv, &status)) | ||
449 | status = 1; | ||
450 | argcv_free (argc, argv); | ||
451 | } | ||
452 | return status; | ||
453 | } | ||
454 | |||
424 | int | 455 | int |
425 | run_mailcap (mu_mailcap_entry_t entry, const char *type) | 456 | run_mailcap (mu_mailcap_entry_t entry, const char *type) |
426 | { | 457 | { |
... | @@ -436,10 +467,24 @@ run_mailcap (mu_mailcap_entry_t entry, const char *type) | ... | @@ -436,10 +467,24 @@ run_mailcap (mu_mailcap_entry_t entry, const char *type) |
436 | if (debug_level > 1) | 467 | if (debug_level > 1) |
437 | dump_mailcap_entry (entry); | 468 | dump_mailcap_entry (entry); |
438 | 469 | ||
470 | if (run_test (entry, type)) | ||
471 | return -1; | ||
472 | |||
473 | if (interactive) | ||
474 | { | ||
439 | mu_mailcap_entry_get_viewcommand (entry, NULL, 0, &size); | 475 | mu_mailcap_entry_get_viewcommand (entry, NULL, 0, &size); |
440 | size++; | 476 | size++; |
441 | view_command = xmalloc (size); | 477 | view_command = xmalloc (size); |
442 | mu_mailcap_entry_get_viewcommand (entry, view_command, size, NULL); | 478 | mu_mailcap_entry_get_viewcommand (entry, view_command, size, NULL); |
479 | } | ||
480 | else | ||
481 | { | ||
482 | if (mu_mailcap_entry_get_value (entry, "print", NULL, 0, &size)) | ||
483 | return 1; | ||
484 | size++; | ||
485 | view_command = xmalloc (size); | ||
486 | mu_mailcap_entry_get_value (entry, "print", view_command, size, NULL); | ||
487 | } | ||
443 | 488 | ||
444 | /* NOTE: We don't create temporary file for %s, we just use | 489 | /* NOTE: We don't create temporary file for %s, we just use |
445 | mimeview_file instead */ | 490 | mimeview_file instead */ |
... | @@ -449,11 +494,15 @@ run_mailcap (mu_mailcap_entry_t entry, const char *type) | ... | @@ -449,11 +494,15 @@ run_mailcap (mu_mailcap_entry_t entry, const char *type) |
449 | pfd = &fd; | 494 | pfd = &fd; |
450 | DEBUG (0, (_("Executing %s...\n"), view_command)); | 495 | DEBUG (0, (_("Executing %s...\n"), view_command)); |
451 | 496 | ||
452 | if (dry_run) | 497 | if (dry_run || !confirm_action (type, view_command)) |
453 | return 0; | 498 | { |
499 | free (view_command); | ||
500 | return 1; | ||
501 | } | ||
454 | 502 | ||
455 | flag = 0; | 503 | flag = 0; |
456 | if (mu_mailcap_entry_copiousoutput (entry, &flag) == 0 && flag) | 504 | if (interactive |
505 | && mu_mailcap_entry_copiousoutput (entry, &flag) == 0 && flag) | ||
457 | pager_pid = create_filter (get_pager (), -1, &outfd); | 506 | pager_pid = create_filter (get_pager (), -1, &outfd); |
458 | 507 | ||
459 | pid = create_filter (view_command, outfd, pfd); | 508 | pid = create_filter (view_command, outfd, pfd); |
... | @@ -483,6 +532,72 @@ run_mailcap (mu_mailcap_entry_t entry, const char *type) | ... | @@ -483,6 +532,72 @@ run_mailcap (mu_mailcap_entry_t entry, const char *type) |
483 | print_exit_status (status); | 532 | print_exit_status (status); |
484 | } | 533 | } |
485 | free (view_command); | 534 | free (view_command); |
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int | ||
539 | find_entry (const char *file, const char *type) | ||
540 | { | ||
541 | mu_mailcap_t mailcap; | ||
542 | int status; | ||
543 | stream_t stream; | ||
544 | int rc = 1; | ||
545 | |||
546 | DEBUG (2, (_("Trying %s...\n"), file)); | ||
547 | status = file_stream_create (&stream, file, MU_STREAM_READ); | ||
548 | if (status) | ||
549 | { | ||
550 | mu_error ("cannot create file stream %s: %s", | ||
551 | file, mu_strerror (status)); | ||
552 | return -1; | ||
553 | } | ||
554 | |||
555 | status = stream_open (stream); | ||
556 | if (status) | ||
557 | { | ||
558 | stream_destroy (&stream, stream_get_owner (stream)); | ||
559 | if (status != ENOENT) | ||
560 | mu_error ("cannot open file stream %s: %s", | ||
561 | file, mu_strerror (status)); | ||
562 | return -1; | ||
563 | } | ||
564 | |||
565 | status = mu_mailcap_create (&mailcap, stream); | ||
566 | if (status == 0) | ||
567 | { | ||
568 | size_t i, count = 0; | ||
569 | |||
570 | mu_mailcap_entries_count (mailcap, &count); | ||
571 | for (i = 1; i <= count; i++) | ||
572 | { | ||
573 | mu_mailcap_entry_t entry; | ||
574 | char buffer[256]; | ||
575 | |||
576 | if (mu_mailcap_get_entry (mailcap, i, &entry)) | ||
577 | continue; | ||
578 | |||
579 | /* typefield. */ | ||
580 | mu_mailcap_entry_get_typefield (entry, | ||
581 | buffer, sizeof (buffer), NULL); | ||
582 | |||
583 | if (fnmatch (buffer, type, FNM_CASEFOLD) == 0) | ||
584 | { | ||
585 | DEBUG (2, (_("Found in %s\n"), file)); | ||
586 | if (run_mailcap (entry, type) == 0) | ||
587 | { | ||
588 | rc = 0; | ||
589 | break; | ||
590 | } | ||
591 | } | ||
592 | } | ||
593 | mu_mailcap_destroy (&mailcap); | ||
594 | } | ||
595 | else | ||
596 | { | ||
597 | mu_error ("cannot create mailcap for %s: %s", | ||
598 | file, mu_strerror (status)); | ||
599 | } | ||
600 | return rc; | ||
486 | } | 601 | } |
487 | 602 | ||
488 | void | 603 | void |
... | @@ -490,8 +605,6 @@ display_file_mailcap (const char *type) | ... | @@ -490,8 +605,6 @@ display_file_mailcap (const char *type) |
490 | { | 605 | { |
491 | char *p, *sp; | 606 | char *p, *sp; |
492 | char *mailcap_path; | 607 | char *mailcap_path; |
493 | mu_mailcap_t mailcap = NULL; | ||
494 | mu_mailcap_entry_t entry = NULL; | ||
495 | 608 | ||
496 | mailcap_path = getenv ("MAILCAP"); | 609 | mailcap_path = getenv ("MAILCAP"); |
497 | if (!mailcap_path) | 610 | if (!mailcap_path) |
... | @@ -506,13 +619,9 @@ display_file_mailcap (const char *type) | ... | @@ -506,13 +619,9 @@ display_file_mailcap (const char *type) |
506 | 619 | ||
507 | for (p = strtok_r (mailcap_path, ":", &sp); p; p = strtok_r (NULL, ":", &sp)) | 620 | for (p = strtok_r (mailcap_path, ":", &sp); p; p = strtok_r (NULL, ":", &sp)) |
508 | { | 621 | { |
509 | if (find_entry (p, type, &entry, &mailcap)) | 622 | if (find_entry (p, type) == 0) |
510 | { | ||
511 | run_mailcap (entry, type); | ||
512 | mu_mailcap_destroy (&mailcap); | ||
513 | break; | 623 | break; |
514 | } | 624 | } |
515 | } | ||
516 | } | 625 | } |
517 | 626 | ||
518 | void | 627 | void |
... | @@ -521,19 +630,22 @@ display_file (const char *type) | ... | @@ -521,19 +630,22 @@ display_file (const char *type) |
521 | if (metamail) | 630 | if (metamail) |
522 | { | 631 | { |
523 | int status; | 632 | int status; |
524 | const char *argv[6]; | 633 | const char *argv[7]; |
525 | 634 | ||
526 | argv[0] = "metamail"; | 635 | argv[0] = "metamail"; |
527 | argv[1] = "-b"; | 636 | argv[1] = "-b"; |
528 | argv[2] = "-c"; | 637 | |
529 | argv[3] = type; | 638 | argv[2] = interactive ? "-p" : "-h"; |
530 | argv[4] = mimeview_file; | 639 | |
531 | argv[5] = NULL; | 640 | argv[3] = "-c"; |
641 | argv[4] = type; | ||
642 | argv[5] = mimeview_file; | ||
643 | argv[6] = NULL; | ||
532 | 644 | ||
533 | if (debug_level) | 645 | if (debug_level) |
534 | { | 646 | { |
535 | char *string; | 647 | char *string; |
536 | argcv_string (5, argv, &string); | 648 | argcv_string (6, argv, &string); |
537 | printf (_("Executing %s...\n"), string); | 649 | printf (_("Executing %s...\n"), string); |
538 | free (string); | 650 | free (string); |
539 | } | 651 | } | ... | ... |
-
Please register or sign in to post a comment