New command: mailutils stat
* include/mailutils/util.h (mu_c_storage_t): New data type. * mu/stat.c: New file. * mu/Makefile.am: Add stat * doc/texinfo/programs.texi: Document mailutils stat
Showing
4 changed files
with
473 additions
and
0 deletions
... | @@ -7816,6 +7816,7 @@ with Mailutils. | ... | @@ -7816,6 +7816,7 @@ with Mailutils. |
7816 | * mailutils info:: Show Mailutils configuration. | 7816 | * mailutils info:: Show Mailutils configuration. |
7817 | * mailutils cflags:: Show compiler options. | 7817 | * mailutils cflags:: Show compiler options. |
7818 | * mailutils ldflags:: List libraries required to link. | 7818 | * mailutils ldflags:: List libraries required to link. |
7819 | * mailutils stat:: Show mailbox status. | ||
7819 | * mailutils query:: Query configuration values. | 7820 | * mailutils query:: Query configuration values. |
7820 | * mailutils 2047:: Decode/encode email message headers. | 7821 | * mailutils 2047:: Decode/encode email message headers. |
7821 | * mailutils filter:: Apply a chain of filters to the input. | 7822 | * mailutils filter:: Apply a chain of filters to the input. |
... | @@ -8004,6 +8005,75 @@ Provide Guile language bindings. | ... | @@ -8004,6 +8005,75 @@ Provide Guile language bindings. |
8004 | Provide Python language bindings. | 8005 | Provide Python language bindings. |
8005 | @end table | 8006 | @end table |
8006 | 8007 | ||
8008 | @node mailutils stat | ||
8009 | @subsection mailutils stat | ||
8010 | The command @command{mailutils stat} shows status of a mailbox. The | ||
8011 | name or URL of the mailbox to operate upon is supplied in the first | ||
8012 | argument. If not given, the command will display status of the | ||
8013 | invoking user system mailbox. | ||
8014 | |||
8015 | @example | ||
8016 | $ mailutils stat | ||
8017 | type: maildir | ||
8018 | path: /var/mail/smith | ||
8019 | URL: /var/mail/smith | ||
8020 | size: 3498 | ||
8021 | messages: 24 | ||
8022 | recent messages: 3 | ||
8023 | first unseen: 20 | ||
8024 | uidvalidity: 1338543026 | ||
8025 | next uid: 87 | ||
8026 | access: 2016-12-15 09:15:08 +0200 | ||
8027 | @end example | ||
8028 | |||
8029 | The output format is controlled by the @option{--format} (@option{-c}) | ||
8030 | option. Its argument is the desired format string, composed of | ||
8031 | ordinary characters, which are reporduced on standard output verbatim, | ||
8032 | backslash sequences, and format specifiers, beginning with @samp{%}. | ||
8033 | |||
8034 | @dfn{Backslash sequences} are interpreted as in C. | ||
8035 | |||
8036 | A @dfn{format specifier} consists of a leading @samp{%} followed by a | ||
8037 | letter. Optional @samp{:} may occur between @samp{%} and the letter. | ||
8038 | Its presense instructs the program to print the description of the | ||
8039 | corresponding value before the value itself. | ||
8040 | |||
8041 | The following format sequences are understood: | ||
8042 | |||
8043 | @table @asis | ||
8044 | @item %f | ||
8045 | Name of the mailbox as supplied in the command line. If | ||
8046 | @command{mailutils stat} was used without explicit mailbox argument, | ||
8047 | @samp{%f} is equivalent to @samp{%U}. | ||
8048 | @item %t | ||
8049 | Type of the mailbox (@samp{mbox}, @samp{maildir}, etc.). The | ||
8050 | description string is @samp{type}. | ||
8051 | @item %p | ||
8052 | Path to the mailbox. In case of remote mailboxes, it is the path | ||
8053 | part of the mailbox URL. Description string: @samp{path}. | ||
8054 | @item %U | ||
8055 | URL of the mailbox. Description string: @samp{URL}. | ||
8056 | @item %s | ||
8057 | Size of the mailbox in octets. Description string: @samp{size}. | ||
8058 | @item %c | ||
8059 | Number of messages in the mailbox. Description string: | ||
8060 | @samp{messages}. | ||
8061 | @item %r | ||
8062 | Number of recent (unread) messages in the mailbox. Description string: | ||
8063 | @samp{recent messages}. | ||
8064 | @item %u | ||
8065 | Index of the first unseen message. Description string: @samp{first unseen}. | ||
8066 | @item %v | ||
8067 | The UIDVALIDITY value. Description string: @samp{uidvalidity}. | ||
8068 | @item %n | ||
8069 | The UID value which will be assigned to the new message to be | ||
8070 | incorporated into the mailbox. Description string: @samp{next uid}. | ||
8071 | @item %a | ||
8072 | Access time of the mailbox, as a number of seconds since the epoch. | ||
8073 | @item %A | ||
8074 | Access time of the mailbox in human-readable format. | ||
8075 | @end table | ||
8076 | |||
8007 | @node mailutils query | 8077 | @node mailutils query |
8008 | @subsection mailutils query | 8078 | @subsection mailutils query |
8009 | The @command{mailutils query} command queries values from Mailutils | 8079 | The @command{mailutils query} command queries values from Mailutils | ... | ... |
... | @@ -23,6 +23,7 @@ | ... | @@ -23,6 +23,7 @@ |
23 | 23 | ||
24 | #include <mailutils/list.h> | 24 | #include <mailutils/list.h> |
25 | #include <mailutils/types.h> | 25 | #include <mailutils/types.h> |
26 | #include <mailutils/cidr.h> | ||
26 | 27 | ||
27 | #ifdef __cplusplus | 28 | #ifdef __cplusplus |
28 | extern "C" { | 29 | extern "C" { |
... | @@ -198,6 +199,25 @@ enum mu_c_type | ... | @@ -198,6 +199,25 @@ enum mu_c_type |
198 | }; | 199 | }; |
199 | 200 | ||
200 | typedef enum mu_c_type mu_c_type_t; | 201 | typedef enum mu_c_type mu_c_type_t; |
202 | |||
203 | union mu_c_storage | ||
204 | { | ||
205 | char *c_string; | ||
206 | signed short c_short; | ||
207 | unsigned short c_ushort; | ||
208 | int c_int; | ||
209 | unsigned int c_uint; | ||
210 | long c_long; | ||
211 | unsigned long c_ulong; | ||
212 | size_t c_size; | ||
213 | mu_off_t c_off; | ||
214 | time_t c_time; | ||
215 | int c_bool; | ||
216 | struct mu_cidr c_cidr; | ||
217 | }; | ||
218 | |||
219 | typedef union mu_c_storage mu_c_storage_t; | ||
220 | |||
201 | extern char const *mu_c_type_str[]; | 221 | extern char const *mu_c_type_str[]; |
202 | int mu_str_to_c (char const *string, mu_c_type_t type, void *tgt, | 222 | int mu_str_to_c (char const *string, mu_c_type_t type, void *tgt, |
203 | char **errmsg); | 223 | char **errmsg); | ... | ... |
mu/stat.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010-2012, 2014-2016 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 "mu.h" | ||
18 | |||
19 | char stat_docstring[] = N_("display mailbox status"); | ||
20 | char stat_args_doc[] = N_("[MAILBOX]"); | ||
21 | |||
22 | char *format_string = "%:t\n\ | ||
23 | %:p\n\ | ||
24 | %:U\n\ | ||
25 | %:s\n\ | ||
26 | %:c\n\ | ||
27 | %:r\n\ | ||
28 | %:u\n\ | ||
29 | %:v\n\ | ||
30 | %:n\n\ | ||
31 | %:A\n"; | ||
32 | |||
33 | static struct mu_option stat_options[] = { | ||
34 | { "format", 'c', N_("STRING"), MU_OPTION_DEFAULT, | ||
35 | N_("defines output format"), | ||
36 | mu_c_string, &format_string }, | ||
37 | MU_OPTION_END | ||
38 | }; | ||
39 | |||
40 | #define prcat2(a, b) a ## b | ||
41 | #define PR_C(field, fmt) \ | ||
42 | static void \ | ||
43 | prcat2(pr_,field) (mu_c_storage_t *stor) \ | ||
44 | { \ | ||
45 | mu_printf (fmt, stor->field); \ | ||
46 | } \ | ||
47 | |||
48 | PR_C(c_string, "%s") | ||
49 | PR_C(c_short, "%hd") | ||
50 | PR_C(c_ushort, "%hu") | ||
51 | PR_C(c_int, "%d") | ||
52 | PR_C(c_uint, "%u") | ||
53 | PR_C(c_long, "%ld") | ||
54 | PR_C(c_ulong, "%lu") | ||
55 | PR_C(c_size, "%zu") | ||
56 | PR_C(c_off, "%" MU_PRI_OFF_T) | ||
57 | |||
58 | static void | ||
59 | pr_c_time (mu_c_storage_t *stor) | ||
60 | { | ||
61 | mu_printf ("%lu", (unsigned long)stor->c_time); | ||
62 | } | ||
63 | |||
64 | static void | ||
65 | pr_c_time_h (mu_c_storage_t *stor) | ||
66 | { | ||
67 | struct tm *tm = localtime (&stor->c_time); | ||
68 | mu_c_streamftime (mu_strout, "%Y-%m-%d %H:%M:%S %Z", tm, NULL); | ||
69 | } | ||
70 | |||
71 | static void (*c_fmt[]) (mu_c_storage_t *stor) = { | ||
72 | #define D(t) [prcat2(mu_,t)] = prcat2(pr_,t) | ||
73 | D(c_string), | ||
74 | D(c_short), | ||
75 | D(c_ushort), | ||
76 | D(c_int), | ||
77 | D(c_uint), | ||
78 | D(c_long), | ||
79 | D(c_ulong), | ||
80 | D(c_size), | ||
81 | D(c_off), | ||
82 | D(c_time) | ||
83 | #undef D | ||
84 | }; | ||
85 | |||
86 | static void | ||
87 | mu_c_output (mu_c_type_t type, mu_c_storage_t *cstor) | ||
88 | { | ||
89 | if (c_fmt[type]) | ||
90 | c_fmt[type] (cstor); | ||
91 | else | ||
92 | abort (); | ||
93 | } | ||
94 | |||
95 | struct mbox_property | ||
96 | { | ||
97 | char fmt; | ||
98 | char *title; | ||
99 | mu_c_type_t type; | ||
100 | int (*fun) (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
101 | void (*prt) (mu_c_storage_t *stor); | ||
102 | }; | ||
103 | |||
104 | static int get_type (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
105 | static int get_path (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
106 | static int get_url (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
107 | static int get_size (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
108 | static int get_count (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
109 | static int get_recent (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
110 | static int get_unseen (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
111 | static int get_uidvalidity (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
112 | static int get_uidnext (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
113 | static int get_atime (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
114 | static int get_name (mu_mailbox_t, char const *, mu_c_storage_t *); | ||
115 | |||
116 | static struct mbox_property proptab[] = { | ||
117 | { 't', N_("type"), mu_c_string, get_type }, | ||
118 | { 'p', N_("path"), mu_c_string, get_path }, | ||
119 | { 'U', N_("URL"), mu_c_string, get_url }, | ||
120 | { 's', N_("size"), mu_c_off, get_size }, | ||
121 | { 'c', N_("messages"), mu_c_size, get_count }, | ||
122 | { 'r', N_("recent messages"), mu_c_size, get_recent }, | ||
123 | { 'u', N_("first unseen"), mu_c_size, get_unseen }, | ||
124 | { 'v', N_("uidvalidity"), mu_c_ulong, get_uidvalidity }, | ||
125 | { 'n', N_("next uid"), mu_c_size, get_uidnext }, | ||
126 | { 'a', N_("access"), mu_c_time, get_atime }, | ||
127 | { 'A', N_("access"), mu_c_time, get_atime, pr_c_time_h }, | ||
128 | { 'f', N_("name"), mu_c_string, get_name }, | ||
129 | { 0 } | ||
130 | }; | ||
131 | |||
132 | static struct mbox_property * | ||
133 | propfmt (int fmt) | ||
134 | { | ||
135 | struct mbox_property *p; | ||
136 | for (p = proptab; p->fmt; p++) | ||
137 | if (p->fmt == fmt) | ||
138 | return p; | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | static char const * | ||
143 | fmtspec (char const *fmt, mu_mailbox_t mbx, const char *name) | ||
144 | { | ||
145 | int c; | ||
146 | int title = 0; | ||
147 | struct mbox_property *prop; | ||
148 | |||
149 | if (!*++fmt) | ||
150 | { | ||
151 | mu_stream_write (mu_strout, fmt - 1, 1, NULL); | ||
152 | return fmt; | ||
153 | } | ||
154 | |||
155 | c = *fmt++; | ||
156 | |||
157 | if (c == '%') | ||
158 | { | ||
159 | mu_stream_write (mu_strout, fmt - 1, 1, NULL); | ||
160 | return fmt; | ||
161 | } | ||
162 | |||
163 | if (c == ':') | ||
164 | { | ||
165 | if (*fmt == 0) | ||
166 | { | ||
167 | mu_stream_write (mu_strout, fmt - 2, 2, NULL); | ||
168 | return fmt; | ||
169 | } | ||
170 | c = *fmt++; | ||
171 | title = 1; | ||
172 | } | ||
173 | prop = propfmt (c); | ||
174 | if (prop) | ||
175 | { | ||
176 | int rc; | ||
177 | mu_c_storage_t cstor; | ||
178 | if (title) | ||
179 | mu_printf ("%s: ", gettext (prop->title)); | ||
180 | rc = prop->fun (mbx, name, &cstor); | ||
181 | switch (rc) | ||
182 | { | ||
183 | case 0: | ||
184 | if (prop->prt) | ||
185 | prop->prt (&cstor); | ||
186 | else | ||
187 | mu_c_output (prop->type, &cstor); | ||
188 | if (prop->type == mu_c_string) | ||
189 | free (cstor.c_string); | ||
190 | break; | ||
191 | |||
192 | case MU_ERR_EMPTY_VFN: | ||
193 | case ENOSYS: | ||
194 | mu_printf (_("N/A")); | ||
195 | break; | ||
196 | |||
197 | default: | ||
198 | mu_printf ("[%s]", mu_strerror (rc)); | ||
199 | } | ||
200 | } | ||
201 | else | ||
202 | mu_stream_write (mu_strout, "?", 1, NULL); | ||
203 | return fmt; | ||
204 | } | ||
205 | |||
206 | void | ||
207 | format_stat (char const *fmt, mu_mailbox_t mbx, const char *name) | ||
208 | { | ||
209 | int c; | ||
210 | |||
211 | while (*fmt) | ||
212 | { | ||
213 | switch (*fmt) | ||
214 | { | ||
215 | case '%': | ||
216 | fmt = fmtspec (fmt, mbx, name); | ||
217 | break; | ||
218 | |||
219 | case '\\': | ||
220 | if (fmt[1] && (c = mu_wordsplit_c_unquote_char (fmt[1]))) | ||
221 | { | ||
222 | mu_printf ("%c", c); | ||
223 | fmt += 2; | ||
224 | break; | ||
225 | } | ||
226 | /* fall through */ | ||
227 | default: | ||
228 | mu_stream_write (mu_strout, fmt, 1, NULL); | ||
229 | if (*fmt == '\n' && fmt[1] == 0) | ||
230 | return; | ||
231 | fmt++; | ||
232 | } | ||
233 | } | ||
234 | mu_printf ("\n"); | ||
235 | } | ||
236 | |||
237 | int | ||
238 | mutool_stat (int argc, char **argv) | ||
239 | { | ||
240 | int rc; | ||
241 | mu_mailbox_t mbox; | ||
242 | const char *name; | ||
243 | |||
244 | mu_register_all_mbox_formats (); | ||
245 | |||
246 | mu_action_getopt (&argc, &argv, stat_options, stat_docstring, stat_args_doc); | ||
247 | if (argc > 1) | ||
248 | { | ||
249 | mu_error (_("too many arguments")); | ||
250 | return EX_USAGE; | ||
251 | } | ||
252 | name = argv[0]; | ||
253 | |||
254 | rc = mu_mailbox_create_default (&mbox, name); | ||
255 | if (rc) | ||
256 | { | ||
257 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_default", name, rc); | ||
258 | return EX_UNAVAILABLE; | ||
259 | } | ||
260 | |||
261 | rc = mu_mailbox_open (mbox, MU_STREAM_READ); | ||
262 | if (rc) | ||
263 | { | ||
264 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", name, rc); | ||
265 | return EX_UNAVAILABLE; | ||
266 | } | ||
267 | |||
268 | if (!name) | ||
269 | { | ||
270 | mu_url_t url; | ||
271 | mu_mailbox_get_url (mbox, &url); | ||
272 | name = mu_url_to_string (url); | ||
273 | } | ||
274 | |||
275 | format_stat (format_string, mbox, name); | ||
276 | |||
277 | mu_mailbox_close (mbox); | ||
278 | mu_mailbox_destroy (&mbox); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int | ||
283 | get_type (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
284 | { | ||
285 | mu_url_t url; | ||
286 | int rc; | ||
287 | |||
288 | rc = mu_mailbox_get_url (mbox, &url); | ||
289 | if (rc == 0) | ||
290 | rc = mu_url_aget_scheme (url, &cstor->c_string); | ||
291 | return rc; | ||
292 | } | ||
293 | |||
294 | static int | ||
295 | get_path (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
296 | { | ||
297 | int rc; | ||
298 | mu_url_t url; | ||
299 | |||
300 | rc = mu_mailbox_get_url (mbox, &url); | ||
301 | if (rc == 0) | ||
302 | rc = mu_url_aget_path (url, &cstor->c_string); | ||
303 | return rc; | ||
304 | } | ||
305 | |||
306 | static int | ||
307 | get_url (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
308 | { | ||
309 | mu_url_t url; | ||
310 | int rc; | ||
311 | |||
312 | rc = mu_mailbox_get_url (mbox, &url); | ||
313 | if (rc == 0) | ||
314 | cstor->c_string = mu_strdup (mu_url_to_string (url)); | ||
315 | return rc; | ||
316 | } | ||
317 | |||
318 | static int | ||
319 | get_size (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
320 | { | ||
321 | return mu_mailbox_get_size (mbox, &cstor->c_off); | ||
322 | } | ||
323 | |||
324 | static int | ||
325 | get_count (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
326 | { | ||
327 | return mu_mailbox_messages_count (mbox, &cstor->c_size); | ||
328 | } | ||
329 | |||
330 | static int | ||
331 | get_recent (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
332 | { | ||
333 | return mu_mailbox_messages_recent (mbox, &cstor->c_size); | ||
334 | } | ||
335 | |||
336 | static int | ||
337 | get_unseen (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
338 | { | ||
339 | return mu_mailbox_message_unseen (mbox, &cstor->c_size); | ||
340 | } | ||
341 | |||
342 | static int | ||
343 | get_uidvalidity (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
344 | { | ||
345 | return mu_mailbox_uidvalidity (mbox, &cstor->c_ulong); | ||
346 | } | ||
347 | |||
348 | static int | ||
349 | get_uidnext (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
350 | { | ||
351 | return mu_mailbox_uidnext (mbox, &cstor->c_size); | ||
352 | } | ||
353 | |||
354 | static int | ||
355 | get_atime (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
356 | { | ||
357 | return mu_mailbox_access_time (mbox, &cstor->c_time); | ||
358 | } | ||
359 | |||
360 | static int | ||
361 | get_name (mu_mailbox_t mbox, char const *mbname, mu_c_storage_t *cstor) | ||
362 | { | ||
363 | cstor->c_string = mu_strdup (mbname); | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | MU Setup: stat | ||
369 | mu-handler: mutool_stat | ||
370 | mu-docstring: stat_docstring | ||
371 | End MU Setup: | ||
372 | */ | ||
373 | |||
374 | |||
375 | |||
376 | |||
377 | |||
378 | |||
379 | |||
380 | |||
381 | |||
382 |
-
Please register or sign in to post a comment