Commit b8dc1293 b8dc1293e299380a32992baa98a773282354d459 by Sergey Poznyakoff

Implement msgchk

* mh/msgchk.c: New file.
* mh/Makefile.am: Build msgchk.
* mh/mh_getopt.h: Update.
* mh/.gitignore: Update.
* mh/TODO: Update.
1 parent 9b2c8192
...@@ -23,6 +23,7 @@ mhn ...@@ -23,6 +23,7 @@ mhn
23 mhseq 23 mhseq
24 mhparam 24 mhparam
25 mhpath 25 mhpath
26 msgchk
26 pick 27 pick
27 pick-gram.c 28 pick-gram.c
28 pick-gram.h 29 pick-gram.h
......
...@@ -34,6 +34,7 @@ bin_PROGRAMS = \ ...@@ -34,6 +34,7 @@ bin_PROGRAMS = \
34 mhparam\ 34 mhparam\
35 mhpath\ 35 mhpath\
36 mhseq\ 36 mhseq\
37 msgchk\
37 pick\ 38 pick\
38 prompter\ 39 prompter\
39 refile\ 40 refile\
......
...@@ -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,
......
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