Augmented new_fs() with an additional argument for a default form.
[mmh] / uip / scan.c
1 /*
2 ** scan.c -- display a one-line "scan" listing of folder or messages
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/fmt_scan.h>
11 #include <h/scansbr.h>
12 #include <h/tws.h>
13 #include <h/utils.h>
14 #include <errno.h>
15
16 static struct swit switches[] = {
17 #define CLRSW  0
18         { "clear", 0 },
19 #define NCLRSW  1
20         { "noclear", 0 },
21 #define FORMSW  2
22         { "form formatfile", 0 },
23 #define FMTSW  3
24         { "format string", 5 },
25 #define WIDTHSW  4
26         { "width columns", 0 },
27 #define FILESW  5
28         { "file file", 4 },
29 #define VERSIONSW 6
30         { "version", 0 },
31 #define HELPSW  7
32         { "help", 0 },
33         { NULL, 0 }
34 };
35
36
37 /*
38 ** prototypes
39 */
40 void clear_screen(void);  /* from termsbr.c */
41
42
43 int
44 main(int argc, char **argv)
45 {
46         int clearflag = 0, ontty;
47         int width = 0;
48         int i, state, msgnum;
49         int seqnum[NUMATTRS], unseen, num_unseen_seq = 0;
50         char *cp, *maildir, *file = NULL, *folder = NULL;
51         char *form = NULL, *format = NULL, buf[BUFSIZ];
52         char **argp, *nfs, **arguments;
53         struct msgs_array msgs = { 0, 0, NULL };
54         struct msgs *mp;
55         FILE *in;
56
57 #ifdef LOCALE
58         setlocale(LC_ALL, "");
59 #endif
60         invo_name = mhbasename(argv[0]);
61
62         /* read user profile/context */
63         context_read();
64
65         arguments = getarguments(invo_name, argc, argv, 1);
66         argp = arguments;
67
68         /*
69         ** Parse arguments
70         */
71         while ((cp = *argp++)) {
72                 if (*cp == '-') {
73                         switch (smatch(++cp, switches)) {
74                         case AMBIGSW:
75                                 ambigsw(cp, switches);
76                                 done(1);
77                         case UNKWNSW:
78                                 adios(NULL, "-%s unknown", cp);
79
80                         case HELPSW:
81                                 snprintf(buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name);
82                                 print_help(buf, switches, 1);
83                                 done(1);
84                         case VERSIONSW:
85                                 print_version(invo_name);
86                                 done(1);
87
88                         case CLRSW:
89                                 clearflag++;
90                                 continue;
91                         case NCLRSW:
92                                 clearflag = 0;
93                                 continue;
94
95                         case FORMSW:
96                                 if (!(form = *argp++) || *form == '-')
97                                         adios(NULL, "missing argument to %s",
98                                                         argp[-2]);
99                                 format = NULL;
100                                 continue;
101                         case FMTSW:
102                                 if (!(format = *argp++) || *format == '-')
103                                         adios(NULL, "missing argument to %s",
104                                                         argp[-2]);
105                                 form = NULL;
106                                 continue;
107
108                         case WIDTHSW:
109                                 if (!(cp = *argp++) || *cp == '-')
110                                         adios(NULL, "missing argument to %s",
111                                                         argp[-2]);
112                                 width = atoi(cp);
113                                 continue;
114
115                         case FILESW:
116                                 if (!(cp = *argp++) || (cp[0] == '-' && cp[1]))
117                                         adios(NULL, "missing argument to %s",
118                                                         argp[-2]);
119                                 if (strcmp(file = cp, "-")!=0)
120                                         file = getcpy(expanddir(cp));
121                                 continue;
122                         }
123                 }
124                 if (*cp == '+' || *cp == '@') {
125                         if (folder)
126                                 adios(NULL, "only one folder at a time!");
127                         else
128                                 folder = getcpy(expandfol(cp));
129                 } else
130                         app_msgarg(&msgs, cp);
131         }
132
133         /*
134         ** Get new format string.  Must be before chdir().
135         */
136         nfs = new_fs(form, format, NULL, FORMAT);
137
138         /*
139         ** We are scanning a maildrop file
140         */
141         if (file) {
142                 if (msgs.size)
143                         adios(NULL, "\"msgs\" not allowed with -file");
144                 if (folder)
145                         adios(NULL, "\"+folder\" not allowed with -file");
146
147                 /* check if "file" is really stdin */
148                 if (strcmp(file, "-") == 0) {
149                         in = stdin;
150                         file = "stdin";
151                 } else if (!(in = fopen(file, "r"))) {
152                         adios(file, "unable to open");
153                 }
154
155                 m_unknown(in);
156                 for (msgnum = 1; ; ++msgnum) {
157                         state = scan(in, msgnum, -1, nfs, width, 0, 0,
158                                         NULL, 0L, 1);
159                         if (state != SCNMSG && state != SCNENC)
160                                 break;
161                 }
162                 fclose(in);
163                 done(0);
164         }
165
166         /*
167         ** We are scanning a folder
168         */
169
170         if (!msgs.size)
171                 app_msgarg(&msgs, seq_all);
172         if (!folder)
173                 folder = getcurfol();
174         maildir = toabsdir(folder);
175
176         if (chdir(maildir) == NOTOK)
177                 adios(maildir, "unable to change directory to");
178
179         /* read folder and create message structure */
180         if (!(mp = folder_read(folder)))
181                 adios(NULL, "unable to read folder %s", folder);
182
183         /* check for empty folder */
184         if (mp->nummsg == 0)
185                 adios(NULL, "no messages in %s", folder);
186
187         /* parse all the message ranges/sequences and set SELECTED */
188         for (msgnum = 0; msgnum < msgs.size; msgnum++)
189                 if (!m_convert(mp, msgs.msgs[msgnum]))
190                         done(1);
191         seq_setprev(mp);  /* set the Previous-Sequence */
192
193         context_replace(curfolder, folder);  /* update current folder */
194         seq_save(mp);  /* synchronize message sequences */
195         context_save();  /* save the context file */
196
197         /*
198         ** Get the sequence number for each `unseen' sequence
199         */
200         if (!(cp = context_find(usequence))) {
201                 cp = seq_unseen;  /* use default, if not set */
202         }
203         if (*cp) {
204                 char **ap, *dp;
205
206                 dp = getcpy(cp);
207                 ap = brkstring(dp, " ", "\n");
208                 for (i = 0; ap && *ap; i++, ap++) {
209                         seqnum[i] = seq_getnum(mp, *ap);
210                 }
211                 num_unseen_seq = i;
212                 if (dp) {
213                         free(dp);
214                 }
215         }
216
217         ontty = isatty(fileno(stdout));
218
219         for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
220                 if (is_selected(mp, msgnum)) {
221                         if ((in = fopen(cp = m_name(msgnum), "r")) == NULL) {
222                                 admonish(cp, "unable to open message");
223                                 continue;
224                         }
225
226                         /*
227                         ** Check if message is in any sequence given
228                         ** by Unseen-Sequence profile entry.
229                         */
230                         unseen = 0;
231                         for (i = 0; i < num_unseen_seq; i++) {
232                                 if (in_sequence(mp, seqnum[i], msgnum)) {
233                                         unseen = 1;
234                                         break;
235                                 }
236                         }
237
238                         switch (state = scan(in, msgnum, 0, nfs, width,
239                                                 msgnum == mp->curmsg, unseen,
240                                                 folder, 0L, 1)) {
241                         case SCNMSG:
242                         case SCNENC:
243                         case SCNERR:
244                                 break;
245
246                         default:
247                                 adios(NULL, "scan() botch(%d)", state);
248
249                         case SCNEOF:
250                                 advise(NULL, "message %d: empty", msgnum);
251                                 break;
252                         }
253                         fclose(in);
254                         if (ontty)
255                                 fflush(stdout);
256                 }
257         }
258
259         folder_free(mp);  /* free folder/message structure */
260         if (clearflag)
261                 clear_screen();
262
263         done(0);
264         return 1;
265 }