372568a0e6b637aa6e697b18ab9c8d535bb1b44c
[mmh] / uip / mark.c
1
2 /*
3  * mark.c -- add message(s) to sequences in given folder
4  *        -- delete messages (s) from sequences in given folder
5  *        -- list sequences in given folder
6  *
7  * $Id$
8  *
9  * This code is Copyright (c) 2002, by the authors of nmh.  See the
10  * COPYRIGHT file in the root directory of the nmh distribution for
11  * complete copyright information.
12  */
13
14 #include <h/mh.h>
15 #include <h/utils.h>
16
17 static struct swit switches[] = {
18 #define ADDSW               0
19     { "add", 0 },
20 #define DELSW               1
21     { "delete", 0 },
22 #define LSTSW               2
23     { "list", 0 },
24 #define SEQSW               3
25     { "sequence name", 0 },
26 #define PUBLSW              4
27     { "public", 0 },
28 #define NPUBLSW             5
29     { "nopublic", 0 },
30 #define ZEROSW              6
31     { "zero", 0 },
32 #define NZEROSW             7
33     { "nozero", 0 },
34 #define VERSIONSW           8
35     { "version", 0 },
36 #define HELPSW              9
37     { "help", 0 },
38 #define DEBUGSW            10
39     { "debug", -5 },
40     { NULL, 0 }
41 };
42
43 /*
44  * static prototypes
45  */
46 static void print_debug (struct msgs *);
47 static void seq_printdebug (struct msgs *);
48
49
50 int
51 main (int argc, char **argv)
52 {
53     int addsw = 0, deletesw = 0, debugsw = 0;
54     int listsw = 0, publicsw = -1, zerosw = 0;
55     int seqp = 0, msgnum;
56     char *cp, *maildir, *folder = NULL, buf[BUFSIZ];
57     char **argp, **arguments;
58     char *seqs[NUMATTRS + 1];
59     struct msgs_array msgs = { 0, 0, NULL };
60     struct msgs *mp;
61
62 #ifdef LOCALE
63     setlocale(LC_ALL, "");
64 #endif
65     invo_name = r1bindex (argv[0], '/');
66
67     /* read user profile/context */
68     context_read();
69
70     arguments = getarguments (invo_name, argc, argv, 1);
71     argp = arguments;
72
73     /*
74      * Parse arguments
75      */
76     while ((cp = *argp++)) {
77         if (*cp == '-') {
78             switch (smatch (++cp, switches)) {
79             case AMBIGSW: 
80                 ambigsw (cp, switches);
81                 done (1);
82             case UNKWNSW: 
83                 adios (NULL, "-%s unknown\n", cp);
84
85             case HELPSW: 
86                 snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]",
87                           invo_name);
88                 print_help (buf, switches, 1);
89                 done (1);
90             case VERSIONSW:
91                 print_version(invo_name);
92                 done (1);
93
94             case ADDSW: 
95                 addsw++;
96                 deletesw = listsw = 0;
97                 continue;
98             case DELSW: 
99                 deletesw++;
100                 addsw = listsw = 0;
101                 continue;
102             case LSTSW: 
103                 listsw++;
104                 addsw = deletesw = 0;
105                 continue;
106
107             case SEQSW: 
108                 if (!(cp = *argp++) || *cp == '-')
109                     adios (NULL, "missing argument to %s", argp[-2]);
110
111                 /* check if too many sequences specified */
112                 if (seqp >= NUMATTRS)
113                     adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
114                 seqs[seqp++] = cp;
115                 continue;
116
117             case PUBLSW: 
118                 publicsw = 1;
119                 continue;
120             case NPUBLSW: 
121                 publicsw = 0;
122                 continue;
123
124             case DEBUGSW: 
125                 debugsw++;
126                 continue;
127
128             case ZEROSW: 
129                 zerosw++;
130                 continue;
131             case NZEROSW: 
132                 zerosw = 0;
133                 continue;
134             }
135         }
136         if (*cp == '+' || *cp == '@') {
137             if (folder)
138                 adios (NULL, "only one folder at a time!");
139             else
140                 folder = pluspath (cp);
141         } else
142                 app_msgarg(&msgs, cp);
143     }
144
145     /*
146      * If we haven't specified -add, -delete, or -list,
147      * then use -add if a sequence was specified, else
148      * use -list.
149      */
150     if (!addsw && !deletesw && !listsw) {
151         if (seqp)
152             addsw++;
153         else
154             listsw++;
155     }
156
157     if (!context_find ("path"))
158         free (path ("./", TFOLDER));
159     if (!msgs.size)
160         app_msgarg(&msgs, listsw ? "all" :"cur");
161     if (!folder)
162         folder = getfolder (1);
163     maildir = m_maildir (folder);
164
165     if (chdir (maildir) == NOTOK)
166         adios (maildir, "unable to change directory to");
167
168     /* read folder and create message structure */
169     if (!(mp = folder_read (folder)))
170         adios (NULL, "unable to read folder %s", folder);
171
172     /* print some general debugging info */
173     if (debugsw)
174         print_debug(mp);
175
176     /* check for empty folder */
177     if (mp->nummsg == 0)
178         adios (NULL, "no messages in %s", folder);
179
180     /* parse all the message ranges/sequences and set SELECTED */
181     for (msgnum = 0; msgnum < msgs.size; msgnum++)
182         if (!m_convert (mp, msgs.msgs[msgnum]))
183             done (1);
184
185     if (publicsw == 1 && is_readonly(mp))
186         adios (NULL, "folder %s is read-only, so -public not allowed", folder);
187
188     /*
189      * Make sure at least one sequence has been
190      * specified if we are adding or deleting.
191      */
192     if (seqp == 0 && (addsw || deletesw))
193         adios (NULL, "-%s requires at least one -sequence argument",
194                addsw ? "add" : "delete");
195     seqs[seqp] = NULL;
196
197     /* Adding messages to sequences */
198     if (addsw) {
199         for (seqp = 0; seqs[seqp]; seqp++)
200             if (!seq_addsel (mp, seqs[seqp], publicsw, zerosw))
201                 done (1);
202     }
203
204     /* Deleting messages from sequences */
205     if (deletesw) {
206         for (seqp = 0; seqs[seqp]; seqp++)
207             if (!seq_delsel (mp, seqs[seqp], publicsw, zerosw))
208                 done (1);
209     }
210
211     /* Listing messages in sequences */
212     if (listsw) {
213         if (seqp) {
214             /* print the sequences given */
215             for (seqp = 0; seqs[seqp]; seqp++)
216                 seq_print (mp, seqs[seqp]);
217         } else {
218             /* else print them all */
219             seq_printall (mp);
220         }
221
222         /* print debugging info about SELECTED messages */
223         if (debugsw)
224             seq_printdebug (mp);
225     }
226
227     seq_save (mp);                      /* synchronize message sequences */
228     context_replace (pfolder, folder);  /* update current folder         */
229     context_save ();                    /* save the context file         */
230     folder_free (mp);                   /* free folder/message structure */
231     done (0);
232     return 1;
233 }
234
235
236 /*
237  * Print general debugging info
238  */
239 static void
240 print_debug (struct msgs *mp)
241 {
242     char buf[100];
243
244     printf ("invo_name     = %s\n", invo_name);
245     printf ("mypath        = %s\n", mypath);
246     printf ("defpath       = %s\n", defpath);
247     printf ("ctxpath       = %s\n", ctxpath);
248     printf ("context flags = %s\n", snprintb (buf, sizeof(buf),
249                 (unsigned) ctxflags, DBITS));
250     printf ("foldpath      = %s\n", mp->foldpath);
251     printf ("folder flags  = %s\n\n", snprintb(buf, sizeof(buf),
252                 (unsigned) mp->msgflags, FBITS));
253     printf ("lowmsg=%d hghmsg=%d nummsg=%d curmsg=%d\n",
254         mp->lowmsg, mp->hghmsg, mp->nummsg, mp->curmsg);
255     printf ("lowsel=%d hghsel=%d numsel=%d\n",
256         mp->lowsel, mp->hghsel, mp->numsel);
257     printf ("lowoff=%d hghoff=%d\n\n", mp->lowoff, mp->hghoff);
258 }
259
260
261 /*
262  * Print debugging info about all the SELECTED
263  * messages and the sequences they are in.
264  */
265 static void
266 seq_printdebug (struct msgs *mp)
267 {
268     int msgnum;
269     char buf[100];
270
271     printf ("\n");
272     for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
273         if (is_selected (mp, msgnum))
274             printf ("%*d: %s\n", DMAXFOLDER, msgnum,
275                 snprintb (buf, sizeof(buf),
276                 (unsigned) mp->msgstats[msgnum - mp->lowoff], seq_bits (mp)));
277     }
278 }