1 /* mbpath.c -- help the sysadmin to find the path matching the mailbox
2  *
3  * Copyright (c) 1994-2008 Carnegie Mellon University.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. The name "Carnegie Mellon University" must not be used to
18  *    endorse or promote products derived from this software without
19  *    prior written permission. For permission or any legal
20  *    details, please contact
21  *      Carnegie Mellon University
22  *      Center for Technology Transfer and Enterprise Creation
23  *      4615 Forbes Avenue
24  *      Suite 302
25  *      Pittsburgh, PA  15213
26  *      (412) 268-7393, fax: (412) 268-7395
27  *      innovation@andrew.cmu.edu
28  *
29  * 4. Redistributions of any form whatsoever must retain the following
30  *    acknowledgment:
31  *    "This product includes software developed by Computing Services
32  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33  *
34  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41  */
42 
43 #include <config.h>
44 
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <sysexits.h>
52 #include <fcntl.h>
53 #include <sys/stat.h>
54 #include <sys/param.h>
55 
56 #include "util.h"
57 #include "global.h"
58 #include "mailbox.h"
59 #include "xmalloc.h"
60 #include "mboxlist.h"
61 #include "user.h"
62 
63 /* generated headers are not necessarily in current directory */
64 #include "imap/imap_err.h"
65 
66 extern int optind;
67 extern char *optarg;
68 
69 /* current namespace */
70 static struct namespace mbpath_namespace;
71 
usage(const char * error)72 static int usage(const char *error)
73 {
74     fprintf(stderr,"usage: mbpath [-C <alt_config>] [-l] [-m] [-q] [-s] [-u] [-a|A|D|M|S|U] <mailbox name>...\n");
75     fprintf(stderr, "\n");
76     fprintf(stderr,"\t-a\tprint all values with prefixes\n");
77     fprintf(stderr,"\t-l\tlocal only (exit with error for remote/nonexistent)\n");
78     fprintf(stderr,"\t-m\toutput the path to the metadata files (if different from the message files)\n");
79     fprintf(stderr,"\t-q\tquietly drop any error messages\n");
80     fprintf(stderr,"\t-s\tstop on error\n");
81     fprintf(stderr,"\t-u\targuments are user, not mailbox\n");
82     fprintf(stderr,"\t-A\tpartition archive directory\n");
83     fprintf(stderr,"\t-D\tpartition data directory (*default*)\n");
84     fprintf(stderr,"\t-M\tpartition metadata file directory (duplicate of -m)\n");
85     fprintf(stderr,"\t-S\tsieve directory for the user\n");
86     fprintf(stderr,"\t-U\tuser files directory (seen, sub, etc)\n");
87     if (error) {
88         fprintf(stderr,"\n");
89         fprintf(stderr,"ERROR: %s", error);
90     }
91     exit(-1);
92 }
93 
main(int argc,char ** argv)94 int main(int argc, char **argv)
95 {
96     mbentry_t *mbentry = NULL;
97     int r, i;
98     int opt;              /* getopt() returns an int */
99     char *alt_config = NULL;
100 
101     // capture options
102     int quiet = 0;
103     int stop_on_error = 0;
104     int localonly = 0;
105     int usermode = 0;
106     int doall = 0;
107     int doA = 0;
108     int doD = 1; // default
109     int doM = 0;
110     int doS = 0;
111     int doU = 0;
112     int sel = 0;
113 
114     while ((opt = getopt(argc, argv, "C:almqsuADMSU")) != EOF) {
115         switch(opt) {
116         case 'C': /* alt config file */
117             alt_config = optarg;
118             break;
119 
120         case 'a':
121             if (sel)
122                 usage("Duplicate selectors given");
123             doall = 1;
124             doD = 0;
125             sel = 1;
126             break;
127 
128         case 'l':
129             localonly = 1;
130             break;
131 
132         case 'm':
133             if (sel)
134                 usage("Duplicate selectors given");
135             doM = 1;
136             doD = 0;
137             sel = 1;
138             break;
139 
140         case 'q':
141             quiet = 1;
142             break;
143 
144         case 's':
145             stop_on_error = 1;
146             break;
147 
148         case 'u':
149             usermode = 1;
150             break;
151 
152         case 'A':
153             if (sel)
154                 usage("Duplicate selectors given");
155             doA = 1;
156             doD = 0;
157             sel = 1;
158             break;
159 
160         case 'D':
161             if (sel)
162                 usage("Duplicate selectors given");
163             sel = 1;
164             break;
165 
166         case 'M':
167             if (sel)
168                 usage("Duplicate selectors given");
169             doM = 1;
170             doD = 0;
171             sel = 1;
172             break;
173 
174         case 'S':
175             if (sel)
176                 usage("Duplicate selectors given");
177             doS = 1;
178             doD = 0;
179             sel = 1;
180             break;
181 
182         case 'U':
183             if (sel)
184                 usage("Duplicate selectors given");
185             doU = 1;
186             doD = 0;
187             sel = 1;
188             break;
189 
190         default:
191             usage(NULL);
192         }
193     }
194 
195     cyrus_init(alt_config, "mbpath", 0, 0);
196 
197 
198     r = mboxname_init_namespace(&mbpath_namespace, 1);
199     if (r) {
200         fatal(error_message(r), -1);
201     }
202 
203     for (i = optind; i < argc; i++) {
204         /* Translate mailboxname */
205         mbname_t *mbname = NULL;
206         if (usermode) {
207             mbname = mbname_from_userid(argv[i]);
208         }
209         else {
210             mbname = mbname_from_extname(argv[i], &mbpath_namespace, NULL);
211         }
212         r = mboxlist_lookup(mbname_intname(mbname), &mbentry, NULL);
213         if (!r) {
214             if (mbentry->mbtype & MBTYPE_REMOTE) {
215                 if (localonly) {
216                     if (stop_on_error) {
217                         if (quiet) {
218                             fatal("", -1);
219                         }
220                         else {
221                             fatal("Non-local mailbox. Stopping\n", -1);
222                         }
223                     }
224                 }
225                 else {
226                     // ignore all selectors and just print this
227                     printf("%s!%s\n", mbentry->server, mbentry->partition);
228                 }
229             }
230             else {
231                 if (doall || doA) {
232                     const char *path = mboxname_archivepath(mbentry->partition, mbentry->name, mbentry->uniqueid, 0);
233                     if (doall) printf("Archive: ");
234                     printf("%s\n", path);
235                 }
236                 if (doall || doD) {
237                     const char *path = mboxname_datapath(mbentry->partition, mbentry->name, mbentry->uniqueid, 0);
238                     if (doall) printf("Data: ");
239                     printf("%s\n", path);
240                 }
241                 if (doall || doM) {
242                     const char *path = mboxname_metapath(mbentry->partition, mbentry->name, mbentry->uniqueid, 0, 0);
243                     if (doall) printf("Meta: ");
244                     printf("%s\n", path);
245                 }
246                 if (doall || doS) {
247                     const char *path = user_sieve_path(mbname_userid(mbname));
248                     if (doall) printf("Sieve: ");
249                     printf("%s\n", path);
250                 }
251                 if (doall || doU) {
252                     // different interface - caller must free
253                     char *path = mboxname_conf_getpath(mbname, NULL);
254                     if (doall) printf("User: ");
255                     printf("%s\n", path);
256                     free(path);
257                 }
258             }
259         }
260         else {
261             if (!quiet && (r == IMAP_MAILBOX_NONEXISTENT)) {
262                 fprintf(stderr, "Invalid mailbox name: %s\n", argv[i]);
263             }
264             if (stop_on_error) {
265                 if (quiet) {
266                     fatal("", -1);
267                 }
268                 else {
269                     fatal("Error in processing mailbox. Stopping\n", -1);
270                 }
271             }
272         }
273         mbname_free(&mbname);
274     }
275 
276     cyrus_done();
277 
278     return 0;
279 }
280