Implement msgchk
* mh/msgchk.c: New file. * mh/Makefile.am: Build msgchk. * mh/mh_getopt.h: Update. * mh/.gitignore: Update. * mh/TODO: Update.
Showing
5 changed files
with
406 additions
and
1 deletions
... | @@ -41,6 +41,7 @@ State Nice Utility Comments | ... | @@ -41,6 +41,7 @@ State Nice Utility Comments |
41 | + 10 whatnow | 41 | + 10 whatnow |
42 | + 20 sortm | 42 | + 20 sortm |
43 | + 20 prompter | 43 | + 20 prompter |
44 | * 20 msgchk --date functionality not implemented | ||
44 | 45 | ||
45 | Utilities In Alphabetical Order | 46 | Utilities In Alphabetical Order |
46 | =============================== | 47 | =============================== |
... | @@ -55,6 +56,7 @@ mark | ... | @@ -55,6 +56,7 @@ mark |
55 | mhl | 56 | mhl |
56 | mhn | 57 | mhn |
57 | mhpath | 58 | mhpath |
59 | msgchk | ||
58 | pick | 60 | pick |
59 | prompter | 61 | prompter |
60 | refile | 62 | refile | ... | ... |
... | @@ -46,6 +46,7 @@ enum mh_arg { | ... | @@ -46,6 +46,7 @@ enum mh_arg { |
46 | ARG_ALL, | 46 | ARG_ALL, |
47 | ARG_AND, | 47 | ARG_AND, |
48 | ARG_ANNOTATE, | 48 | ARG_ANNOTATE, |
49 | ARG_APOP, | ||
49 | ARG_AUDIT, | 50 | ARG_AUDIT, |
50 | ARG_AUTO, | 51 | ARG_AUTO, |
51 | ARG_BEFORE, | 52 | ARG_BEFORE, |
... | @@ -83,6 +84,7 @@ enum mh_arg { | ... | @@ -83,6 +84,7 @@ enum mh_arg { |
83 | ARG_FROM, | 84 | ARG_FROM, |
84 | ARG_GROUP, | 85 | ARG_GROUP, |
85 | ARG_HEADER, | 86 | ARG_HEADER, |
87 | ARG_HOST, | ||
86 | ARG_INPLACE, | 88 | ARG_INPLACE, |
87 | ARG_INTERACTIVE, | 89 | ARG_INTERACTIVE, |
88 | ARG_LBRACE, | 90 | ARG_LBRACE, |
... | @@ -95,6 +97,7 @@ enum mh_arg { | ... | @@ -95,6 +97,7 @@ enum mh_arg { |
95 | ARG_MOVETO, | 97 | ARG_MOVETO, |
96 | ARG_MSGID, | 98 | ARG_MSGID, |
97 | ARG_NOALIAS, | 99 | ARG_NOALIAS, |
100 | ARG_NOAPOP, | ||
98 | ARG_NOAUDIT, | 101 | ARG_NOAUDIT, |
99 | ARG_NOAUTO, | 102 | ARG_NOAUTO, |
100 | ARG_NOBELL, | 103 | ARG_NOBELL, |
... | @@ -114,13 +117,14 @@ enum mh_arg { | ... | @@ -114,13 +117,14 @@ enum mh_arg { |
114 | ARG_NOFORWARD, | 117 | ARG_NOFORWARD, |
115 | ARG_NOHEADER, | 118 | ARG_NOHEADER, |
116 | ARG_NOHEADERS, | 119 | ARG_NOHEADERS, |
117 | ARG_NOINTERACTIVE, | ||
118 | ARG_NOINPLACE, | 120 | ARG_NOINPLACE, |
121 | ARG_NOINTERACTIVE, | ||
119 | ARG_NOLIMIT, | 122 | ARG_NOLIMIT, |
120 | ARG_NOLIST, | 123 | ARG_NOLIST, |
121 | ARG_NOMIME, | 124 | ARG_NOMIME, |
122 | ARG_NOMOREPROC, | 125 | ARG_NOMOREPROC, |
123 | ARG_NOMSGID, | 126 | ARG_NOMSGID, |
127 | ARG_NONOTIFY, | ||
124 | ARG_NOPAUSE, | 128 | ARG_NOPAUSE, |
125 | ARG_NOPUBLIC, | 129 | ARG_NOPUBLIC, |
126 | ARG_NOPUSH, | 130 | ARG_NOPUSH, |
... | @@ -134,6 +138,7 @@ enum mh_arg { | ... | @@ -134,6 +138,7 @@ enum mh_arg { |
134 | ARG_NOSTORE, | 138 | ARG_NOSTORE, |
135 | ARG_NOT, | 139 | ARG_NOT, |
136 | ARG_NOTEXTFIELD, | 140 | ARG_NOTEXTFIELD, |
141 | ARG_NOTIFY, | ||
137 | ARG_NOTOTAL, | 142 | ARG_NOTOTAL, |
138 | ARG_NOTRUNCATE, | 143 | ARG_NOTRUNCATE, |
139 | ARG_NOUSE, | 144 | ARG_NOUSE, | ... | ... |
mh/msgchk.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2013 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils 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 | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #include "mh.h" | ||
18 | #include "mailutils/kwd.h" | ||
19 | #include "mailutils/folder.h" | ||
20 | #include "mailutils/auth.h" | ||
21 | #include <pwd.h> | ||
22 | |||
23 | static char doc[] = N_("GNU MH msgchk")"\v" | ||
24 | N_("Use -help to obtain the list of traditional MH options."); | ||
25 | static char args_doc[] = N_("USER [USER...]"); | ||
26 | |||
27 | /* GNU options */ | ||
28 | static struct argp_option options[] = { | ||
29 | {"date", ARG_DATE, N_("BOOL"), OPTION_ARG_OPTIONAL, | ||
30 | N_("print out the last date mail was read") }, | ||
31 | {"nodate", ARG_NODATE, NULL, OPTION_HIDDEN, | ||
32 | N_("don't print out the last date mail was read") }, | ||
33 | {"notify", ARG_NOTIFY, "all|mail|nomail", 0, | ||
34 | N_("produce a message upon these events") }, | ||
35 | {"nonotify", ARG_NONOTIFY, "all|mail|nomail", 0, | ||
36 | N_("disable notification") }, | ||
37 | {"host", ARG_HOST, N_("URL"), 0, | ||
38 | N_("check mail on this host or URL") }, | ||
39 | {"user", ARG_USER, N_("NAME"), 0, | ||
40 | N_("set user name for remote mailbox access") }, | ||
41 | {"apop", ARG_APOP, N_("BOOL"), OPTION_ARG_OPTIONAL, | ||
42 | N_("enable APOP") }, | ||
43 | {"noapop", ARG_NOAPOP, NULL, OPTION_HIDDEN, | ||
44 | N_("disable APOP") }, | ||
45 | {NULL} | ||
46 | }; | ||
47 | |||
48 | /* Traditional MH options */ | ||
49 | struct mh_option mh_option[] = { | ||
50 | { "date", MH_OPT_BOOL }, | ||
51 | { "notify", MH_OPT_ARG, "all|mail|nomail" }, | ||
52 | { "nonotify", MH_OPT_ARG, "all|mail|nomail" }, | ||
53 | { "host", MH_OPT_ARG, "host-or-url" }, | ||
54 | { "user", MH_OPT_ARG, "name" }, | ||
55 | { "apop", MH_OPT_BOOL }, | ||
56 | { NULL } | ||
57 | }; | ||
58 | |||
59 | int date_option; | ||
60 | int apop_option; | ||
61 | char *remote_host; | ||
62 | char *remote_user; | ||
63 | |||
64 | #define NOTIFY_MAIL 0x1 | ||
65 | #define NOTIFY_NOMAIL 0x2 | ||
66 | #define NOTIFY_ALL (NOTIFY_MAIL|NOTIFY_NOMAIL) | ||
67 | |||
68 | int notify = NOTIFY_ALL; | ||
69 | |||
70 | static struct mu_kwd notifytab[] = { | ||
71 | { "mail", NOTIFY_MAIL }, | ||
72 | { "nomail", NOTIFY_NOMAIL }, | ||
73 | { "all", NOTIFY_ALL }, | ||
74 | { NULL } | ||
75 | }; | ||
76 | |||
77 | static error_t | ||
78 | opt_handler (int key, char *arg, struct argp_state *state) | ||
79 | { | ||
80 | int n; | ||
81 | |||
82 | switch (key) | ||
83 | { | ||
84 | case ARG_DATE: | ||
85 | date_option = is_true (arg); | ||
86 | break; | ||
87 | |||
88 | case ARG_NODATE: | ||
89 | date_option = 0; | ||
90 | break; | ||
91 | |||
92 | case ARG_APOP: | ||
93 | apop_option = is_true (arg); | ||
94 | break; | ||
95 | |||
96 | case ARG_NOAPOP: | ||
97 | apop_option = 0; | ||
98 | break; | ||
99 | |||
100 | case ARG_NOTIFY: | ||
101 | if (mu_kwd_xlat_name (notifytab, arg, &n)) | ||
102 | argp_error (state, "unknown notify argument: %s", arg); | ||
103 | notify |= n; | ||
104 | break; | ||
105 | |||
106 | case ARG_NONOTIFY: | ||
107 | if (mu_kwd_xlat_name (notifytab, arg, &n)) | ||
108 | argp_error (state, "unknown notify argument: %s", arg); | ||
109 | notify &= ~n; | ||
110 | break; | ||
111 | |||
112 | case ARG_USER: | ||
113 | remote_user = arg; | ||
114 | break; | ||
115 | |||
116 | case ARG_HOST: | ||
117 | remote_host = arg; | ||
118 | break; | ||
119 | |||
120 | default: | ||
121 | return ARGP_ERR_UNKNOWN; | ||
122 | } | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static char * | ||
127 | attach_auth_ticket (mu_mailbox_t mbox) | ||
128 | { | ||
129 | char *filename = NULL; | ||
130 | mu_folder_t folder = NULL; | ||
131 | mu_authority_t auth = NULL; | ||
132 | |||
133 | if (mu_mailbox_get_folder (mbox, &folder) == 0 | ||
134 | && mu_folder_get_authority (folder, &auth) == 0 | ||
135 | && auth) | ||
136 | { | ||
137 | mu_wicket_t wicket; | ||
138 | int rc; | ||
139 | |||
140 | filename = mu_tilde_expansion (mu_ticket_file, MU_HIERARCHY_DELIMITER, | ||
141 | NULL); | ||
142 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1, | ||
143 | ("Reading user ticket file %s", filename)); | ||
144 | |||
145 | if ((rc = mu_file_wicket_create (&wicket, filename)) == 0) | ||
146 | { | ||
147 | mu_ticket_t ticket; | ||
148 | |||
149 | if ((rc = mu_wicket_get_ticket (wicket, NULL, &ticket)) == 0) | ||
150 | { | ||
151 | rc = mu_authority_set_ticket (auth, ticket); | ||
152 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1, | ||
153 | ("Retrieved and set ticket: %d", rc)); | ||
154 | } | ||
155 | else | ||
156 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
157 | ("Error retrieving ticket: %s\n", | ||
158 | mu_strerror (rc))); | ||
159 | mu_wicket_destroy (&wicket); | ||
160 | } | ||
161 | else | ||
162 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
163 | ("Error creating wicket: %s\n", mu_strerror (rc))); | ||
164 | if (rc) | ||
165 | { | ||
166 | free (filename); | ||
167 | filename = NULL; | ||
168 | } | ||
169 | } | ||
170 | return filename; | ||
171 | } | ||
172 | |||
173 | int | ||
174 | checkmail (const char *username, int personal) | ||
175 | { | ||
176 | int rc; | ||
177 | mu_url_t url; | ||
178 | mu_mailbox_t mbox; | ||
179 | size_t recent = 0, count = 0; | ||
180 | int status = 1; | ||
181 | int have_user; | ||
182 | |||
183 | if (remote_host) | ||
184 | { | ||
185 | static mu_url_t pop_hint; | ||
186 | |||
187 | if (pop_hint) | ||
188 | { | ||
189 | rc = mu_url_create (&pop_hint, "pop://"); | ||
190 | if (rc) | ||
191 | { | ||
192 | mu_error ("cannot create URL hint: %s", mu_strerror (rc)); | ||
193 | exit (2); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | rc = mu_url_create_hint (&url, remote_host, MU_URL_PARSE_DEFAULT, | ||
198 | pop_hint); | ||
199 | if (rc) | ||
200 | { | ||
201 | mu_diag_funcall (MU_DIAG_ERROR, "mu_url_create_hint", remote_host, | ||
202 | rc); | ||
203 | exit (2); | ||
204 | } | ||
205 | |||
206 | if (apop_option) | ||
207 | { | ||
208 | rc = mu_url_set_auth (url, "+APOP"); | ||
209 | if (rc) | ||
210 | { | ||
211 | mu_diag_funcall (MU_DIAG_ERROR, "mu_url_set_auth", "+APOP", rc); | ||
212 | exit (2); | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | else | ||
217 | { | ||
218 | char *s; | ||
219 | rc = mu_construct_user_mailbox_url (&s, username); | ||
220 | if (rc) | ||
221 | { | ||
222 | mu_diag_funcall (MU_DIAG_ERROR, "mu_construct_user_mailbox_url", | ||
223 | username, rc); | ||
224 | exit (2); | ||
225 | } | ||
226 | |||
227 | rc = mu_url_create (&url, s); | ||
228 | if (rc) | ||
229 | { | ||
230 | mu_diag_funcall (MU_DIAG_ERROR, "mu_url_create", s, rc); | ||
231 | exit (2); | ||
232 | } | ||
233 | free (s); | ||
234 | } | ||
235 | |||
236 | rc = mu_mailbox_create_from_url (&mbox, url); | ||
237 | if (rc) | ||
238 | { | ||
239 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_from_url", | ||
240 | mu_url_to_string (url), rc); | ||
241 | exit (2); | ||
242 | } | ||
243 | |||
244 | if (personal) | ||
245 | { | ||
246 | char *filename = attach_auth_ticket (mbox); | ||
247 | |||
248 | have_user = mu_url_has_flag (url, MU_URL_USER); | ||
249 | if (!have_user) | ||
250 | { | ||
251 | mu_url_t tickurl; | ||
252 | |||
253 | if (mu_wicket_file_match_url (filename, url, MU_URL_PARSE_ALL, | ||
254 | &tickurl) == 0) | ||
255 | { | ||
256 | have_user = mu_url_has_flag (tickurl, MU_URL_USER); | ||
257 | mu_url_destroy (&tickurl); | ||
258 | } | ||
259 | } | ||
260 | free (filename); | ||
261 | } | ||
262 | else | ||
263 | have_user = 0; | ||
264 | |||
265 | if (!have_user) | ||
266 | { | ||
267 | mu_url_t turl; | ||
268 | |||
269 | mu_mailbox_get_url (mbox, &turl); | ||
270 | rc = mu_url_set_user (turl, username); | ||
271 | if (rc) | ||
272 | { | ||
273 | mu_diag_funcall (MU_DIAG_ERROR, "mu_url_set_user", username, rc); | ||
274 | exit (2); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | rc = mu_mailbox_open (mbox, MU_STREAM_READ); | ||
279 | if (rc) | ||
280 | { | ||
281 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", | ||
282 | mu_url_to_string (url), rc); | ||
283 | exit (2); | ||
284 | } | ||
285 | |||
286 | rc = mu_mailbox_messages_count (mbox, &count); | ||
287 | if (rc) | ||
288 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_messages_count", | ||
289 | mu_url_to_string (url), rc); | ||
290 | if (count) | ||
291 | { | ||
292 | status = 0; | ||
293 | |||
294 | if (notify & NOTIFY_MAIL) | ||
295 | { | ||
296 | mu_off_t mbsiz = 0; | ||
297 | |||
298 | rc = mu_mailbox_messages_recent (mbox, &recent); | ||
299 | if (rc) | ||
300 | { | ||
301 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_messages_recent", | ||
302 | mu_url_to_string (url), rc); | ||
303 | |||
304 | mu_mailbox_get_size (mbox, &mbsiz); | ||
305 | if (personal) | ||
306 | mu_printf (ngettext ("You have %lu message", | ||
307 | "You have %lu messages", | ||
308 | count), | ||
309 | (unsigned long) count); | ||
310 | else | ||
311 | mu_printf (ngettext ("%s has %lu message", | ||
312 | "%s has %lu messages", | ||
313 | count), | ||
314 | username, (unsigned long) count); | ||
315 | mu_printf (ngettext (" (%lu byte)", | ||
316 | " (%lu bytes)", | ||
317 | mbsiz), (unsigned long) mbsiz); | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | if (personal) | ||
322 | mu_printf (recent ? _("You have new mail waiting") : | ||
323 | _("You have old mail waiting")); | ||
324 | else | ||
325 | mu_printf (recent ? _("%s has new mail waiting") : | ||
326 | _("%s has old mail waiting"), username); | ||
327 | } | ||
328 | |||
329 | if (date_option) | ||
330 | /*FIXME*/; | ||
331 | |||
332 | mu_printf ("\n"); | ||
333 | } | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | status = 1; | ||
338 | |||
339 | if (notify & NOTIFY_NOMAIL) | ||
340 | { | ||
341 | if (personal) | ||
342 | mu_printf (_("You don't have any mail waiting\n")); | ||
343 | else | ||
344 | mu_printf (_("%s doesn't have any mail waiting\n"), | ||
345 | username); | ||
346 | } | ||
347 | } | ||
348 | mu_mailbox_destroy (&mbox); | ||
349 | |||
350 | return status; | ||
351 | } | ||
352 | |||
353 | int | ||
354 | main (int argc, char **argv) | ||
355 | { | ||
356 | int index; | ||
357 | int rc = 0; | ||
358 | |||
359 | MU_APP_INIT_NLS (); | ||
360 | |||
361 | mh_argp_init (); | ||
362 | mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, | ||
363 | opt_handler, NULL, &index); | ||
364 | |||
365 | argc -= index; | ||
366 | argv += index; | ||
367 | |||
368 | if (argc == 0) | ||
369 | { | ||
370 | if (remote_user) | ||
371 | rc |= checkmail (remote_user, 1); | ||
372 | else | ||
373 | { | ||
374 | struct passwd *pw = getpwuid (getuid ()); | ||
375 | if (!pw) | ||
376 | { | ||
377 | mu_error (_("cannot determine my username")); | ||
378 | return 2; | ||
379 | } | ||
380 | rc |= checkmail (pw->pw_name, 1); | ||
381 | } | ||
382 | } | ||
383 | else if (remote_user) | ||
384 | { | ||
385 | mu_error (_("no arguments are allowed when the -user option is given")); | ||
386 | return 2; | ||
387 | } | ||
388 | else | ||
389 | while (argc--) | ||
390 | rc |= checkmail (*argv++, 0); | ||
391 | |||
392 | return rc; | ||
393 | } | ||
394 | |||
395 | |||
396 |
-
Please register or sign in to post a comment