Commit a103f4b1 a103f4b1198282f8f45400d60757ce3a420011d0 by Sergey Poznyakoff

Handle --no-ask and --no-interactive (-h)

options. Continue search for a matching entry when necessary.
Implement 'test' and 'print' commands.
1 parent 4d65d8c2
...@@ -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 }
......