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