1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library.  If not, see
16    <http://www.gnu.org/licenses/>. */
17 
18 #include <config.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <mailutils/sys/mailcap.h>
22 #include <mailutils/iterator.h>
23 
24 static int
25 finder_init (mu_mailcap_finder_t finder,
26 	     int flags,
27 	     struct mu_mailcap_selector_closure *sc,
28 	     struct mu_mailcap_error_closure *ec,
29 	     char **file_names);
30 
31 int
mu_mailcap_finder_create(mu_mailcap_finder_t * pfinder,int flags,struct mu_mailcap_selector_closure * sc,struct mu_mailcap_error_closure * ec,char ** file_names)32 mu_mailcap_finder_create (mu_mailcap_finder_t *pfinder, int flags,
33 			  struct mu_mailcap_selector_closure *sc,
34 			  struct mu_mailcap_error_closure *ec,
35 			  char **file_names)
36 {
37   int rc;
38   mu_mailcap_finder_t finder;
39 
40   if (!pfinder)
41     return MU_ERR_OUT_PTR_NULL;
42   if (!file_names)
43     return EINVAL;
44   finder = calloc (1, sizeof *finder);
45   if (!finder)
46     return ENOMEM;
47   rc = finder_init (finder, flags, sc, ec, file_names);
48   if (rc)
49     mu_mailcap_finder_destroy (&finder);
50   else
51     *pfinder = finder;
52   return rc;
53 }
54 
55 static int
finder_init(mu_mailcap_finder_t finder,int flags,struct mu_mailcap_selector_closure * sc,struct mu_mailcap_error_closure * ec,char ** file_names)56 finder_init (mu_mailcap_finder_t finder,
57 	     int flags,
58 	     struct mu_mailcap_selector_closure *sc,
59 	     struct mu_mailcap_error_closure *ec,
60 	     char **file_names)
61 {
62   int rc;
63   size_t i;
64 
65   rc = mu_mailcap_create (&finder->mcp);
66   if (rc)
67     return rc;
68   mu_mailcap_set_flags (finder->mcp, flags);
69   if (sc)
70     {
71       rc = mu_mailcap_set_selector (finder->mcp, sc);
72       if (rc)
73 	return rc;
74     }
75   if (ec)
76     {
77       rc = mu_mailcap_set_error (finder->mcp, ec);
78       if (rc)
79 	return rc;
80     }
81 
82   for (i = 0; file_names[i]; i++)
83     {
84       if (access (file_names[i], F_OK))
85 	continue;
86       mu_mailcap_parse_file (finder->mcp, file_names[i]);
87     }
88 
89   return 0;
90 }
91 
92 void
mu_mailcap_finder_destroy(mu_mailcap_finder_t * pfinder)93 mu_mailcap_finder_destroy (mu_mailcap_finder_t *pfinder)
94 {
95   if (pfinder && *pfinder)
96     {
97       mu_mailcap_finder_t finder = *pfinder;
98       mu_iterator_destroy (&finder->itr);
99       mu_mailcap_destroy (&finder->mcp);
100       free (finder);
101       *pfinder = NULL;
102     }
103 }
104 
105 int
mu_mailcap_finder_next_match(mu_mailcap_finder_t finder,mu_mailcap_entry_t * ret_entry)106 mu_mailcap_finder_next_match (mu_mailcap_finder_t finder,
107 			      mu_mailcap_entry_t *ret_entry)
108 {
109   int rc;
110 
111   if (!finder)
112     return EINVAL;
113   if (!ret_entry)
114     return MU_ERR_OUT_PTR_NULL;
115   if (!finder->itr)
116     {
117       rc = mu_mailcap_get_iterator (finder->mcp, &finder->itr);
118       if (rc == 0)
119 	rc = mu_iterator_first (finder->itr);
120     }
121   else
122     rc = mu_iterator_next (finder->itr);
123 
124   if (rc)
125     return rc;
126 
127   if (mu_iterator_is_done (finder->itr))
128     return MU_ERR_NOENT;
129 
130   return mu_iterator_current (finder->itr, (void**) ret_entry);
131 }
132