1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2021 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 /* MH scan command */
18
19 #include <mh.h>
20 #ifdef HAVE_TERMCAP_H
21 # include <termcap.h>
22 #endif
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <time.h>
26 #include <mailutils/observer.h>
27
28 static char prog_doc[] = N_("Produce a one line per message scan listing");
29 static char args_doc[] = N_("[MSGLIST]");
30
31 static int clear;
32
33 static int width;
34 static int reverse;
35 static int header;
36
37 static mh_format_t format;
38 static mh_fvm_t fvm;
39 static mu_msgset_t msgset;
40
41 static struct mu_option options[] = {
42 { "clear", 0, NULL, MU_OPTION_DEFAULT,
43 N_("clear screen after displaying the list"),
44 mu_c_bool, &clear },
45 { "form", 0, N_("FILE"), MU_OPTION_DEFAULT,
46 N_("read format from given file"),
47 mu_c_string, &format, mh_opt_parse_formfile },
48 { "format", 0, N_("FORMAT"), MU_OPTION_DEFAULT,
49 N_("use this format string"),
50 mu_c_string, &format, mh_opt_parse_format },
51 { "header", 0, NULL, MU_OPTION_DEFAULT,
52 N_("display header"),
53 mu_c_bool, &header },
54 { "width", 0, N_("NUMBER"), MU_OPTION_DEFAULT,
55 N_("set output width"),
56 mu_c_int, &width },
57 { "reverse", 0, NULL, MU_OPTION_DEFAULT,
58 N_("list messages in reverse order"),
59 mu_c_bool, &reverse },
60 { "file", 0, N_("FILE"), MU_OPTION_HIDDEN,
61 N_("[not yet implemented]"),
62 mu_c_string, NULL, mh_opt_notimpl },
63 MU_OPTION_END
64 };
65
66 static void print_header (mu_mailbox_t mbox);
67 static void clear_screen (void);
68
69 static int
list_message(size_t num MU_ARG_UNUSED,mu_message_t msg,void * data MU_ARG_UNUSED)70 list_message (size_t num MU_ARG_UNUSED, mu_message_t msg,
71 void *data MU_ARG_UNUSED)
72 {
73 mh_fvm_run (fvm, msg);
74 return 0;
75 }
76
77 /* Observable Action this is called at every message discover. */
78 static int
action(mu_observer_t o,size_t type,void * data,void * action_data)79 action (mu_observer_t o, size_t type, void *data, void *action_data)
80 {
81 static int counter;
82 mu_mailbox_t mbox;
83 mu_message_t msg = NULL;
84
85 if (type == MU_EVT_MESSAGE_ADD)
86 {
87 mbox = mu_observer_get_owner (o);
88 counter++;
89 mu_mailbox_get_message (mbox, counter, &msg);
90 mh_fvm_run (fvm, msg);
91 }
92 return 0;
93 }
94
95 int
main(int argc,char ** argv)96 main (int argc, char **argv)
97 {
98 mu_mailbox_t mbox;
99 int status;
100 size_t total = 0;
101
102 mh_getopt (&argc, &argv, options, MH_GETOPT_DEFAULT_FOLDER,
103 args_doc, prog_doc, NULL);
104 if (!format)
105 format = mh_scan_format ();
106
107 mh_fvm_create (&fvm, MH_FMT_FORCENL);
108 mh_fvm_set_format (fvm, format);
109 mh_fvm_set_width (fvm, width ? width : mh_width ());
110 mh_format_destroy (&format);
111
112 mbox = mh_open_folder (mh_current_folder (), MU_STREAM_READ);
113
114 if ((argc == 0 || strcmp (argv[0], "all") == 0) && !reverse)
115 {
116 /* Fast approach */
117 mu_observer_t observer;
118 mu_observable_t observable;
119
120 print_header (mbox);
121
122 mu_observer_create (&observer, mbox);
123 mu_observer_set_action (observer, action, mbox);
124 mu_mailbox_get_observable (mbox, &observable);
125 mu_observable_attach (observable, MU_EVT_MESSAGE_ADD, observer);
126
127 status = mu_mailbox_scan (mbox, 1, &total);
128 }
129 else
130 {
131 mu_mailbox_messages_count (mbox, &total);
132 mh_msgset_parse (&msgset, mbox, argc, argv, "all");
133
134 print_header (mbox);
135 status = mu_msgset_foreach_dir_message (msgset, reverse,
136 list_message, NULL);
137 }
138
139 if (total == 0)
140 {
141 mu_url_t url = NULL;
142
143 mu_mailbox_get_url (mbox, &url);
144 mu_error (_("no messages in %s"), mu_url_to_string (url));
145 }
146
147 clear_screen ();
148 mh_fvm_destroy (&fvm);
149
150 mh_global_save_state ();
151 mu_mailbox_close (mbox);
152 mu_mailbox_destroy (&mbox);
153
154 return status;
155 }
156
157 static void
print_header(mu_mailbox_t mbox)158 print_header (mu_mailbox_t mbox)
159 {
160 if (header)
161 {
162 mu_url_t url = NULL;
163 char datestr[64];
164 time_t t;
165
166 mu_mailbox_get_url (mbox, &url);
167 time (&t);
168 strftime (datestr, sizeof datestr, "%c", localtime (&t));
169 printf (_("Folder %s %s\n"), mu_url_to_string (url), datestr);
170 }
171 }
172
173 #ifdef HAVE_TERMCAP_H
174 /* A subroutine for tputs */
175 int
putstdout(char c)176 putstdout(char c)
177 {
178 return putc(c, stdout);
179 }
180 #endif
181
182 static void
clear_screen(void)183 clear_screen (void)
184 {
185 if (clear)
186 {
187 #ifdef HAVE_TERMCAP_H
188 if (isatty (1))
189 {
190 char termcap_buf[1024];
191 char *buffer = termcap_buf;
192 char *termname;
193
194 if ((termname = getenv("TERM")) == NULL)
195 /* No terminal; Try ansi */
196 termname = "ansi";
197
198 if (tgetent(termcap_buf, termname) == 1)
199 {
200 char *clr = tgetstr ("cl", &buffer);
201 if (clr)
202 {
203 tputs(clr, 1, (int (*)())putstdout);
204 return;
205 }
206 }
207 }
208 #endif
209 /* Fall back to formfeed */
210 fprintf (stdout, "\f");
211 }
212 }
213