Commit 8571d58b 8571d58b012a8c920073d9b9d139547dd44bd42a by Sergey Poznyakoff

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
1 parent 48bfe14e
...@@ -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);
......
...@@ -59,6 +59,7 @@ MODULES = \ ...@@ -59,6 +59,7 @@ MODULES = \
59 $(POP_C)\ 59 $(POP_C)\
60 query.c\ 60 query.c\
61 send.c\ 61 send.c\
62 stat.c\
62 $(SMTP_C)\ 63 $(SMTP_C)\
63 wicket.c 64 wicket.c
64 65
......
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