xref: /haiku/src/bin/mail_utils/mail2mbox.cpp (revision 66fa08aa81d6a95f8d20cf2d7bc5b3c3472cbfd2)
108c63a2dSAxel Dörfler /*
208c63a2dSAxel Dörfler  * Copyright 2005-2009, Haiku Inc.
308c63a2dSAxel Dörfler  * This file may be used under the terms of the MIT License.
4667176abSJonas Sundström  *
508c63a2dSAxel Dörfler  * Originally public domain written by Alexander G. M. Smith.
6667176abSJonas Sundström  */
7667176abSJonas Sundström 
808c63a2dSAxel Dörfler 
908c63a2dSAxel Dörfler /*!	BeMailToMBox is a utility program (requested by Frank Zschockelt) that
1008c63a2dSAxel Dörfler 	converts BeOS e-mail files into Unix mailbox files (the kind that Pine
1108c63a2dSAxel Dörfler 	uses).  All the files in the input directory are concatenated with the
1208c63a2dSAxel Dörfler 	appropriate mbox header lines added between them, and trailing blank lines
1308c63a2dSAxel Dörfler 	reduced.  The resulting text is written to standard output.  Command line
1408c63a2dSAxel Dörfler 	driven.
1508c63a2dSAxel Dörfler */
1608c63a2dSAxel Dörfler 
1708c63a2dSAxel Dörfler #include <ctype.h>
1808c63a2dSAxel Dörfler #include <errno.h>
1908c63a2dSAxel Dörfler #include <string.h>
2008c63a2dSAxel Dörfler #include <stdio.h>
2108c63a2dSAxel Dörfler #include <time.h>
22667176abSJonas Sundström 
23667176abSJonas Sundström #include <Application.h>
24667176abSJonas Sundström #include <StorageKit.h>
25667176abSJonas Sundström #include <SupportKit.h>
26667176abSJonas Sundström 
27667176abSJonas Sundström 
2808c63a2dSAxel Dörfler extern const char* __progname;
2908c63a2dSAxel Dörfler static const char* kProgramName = __progname;
30667176abSJonas Sundström 
31cc592ed1SAxel Dörfler time_t gDateStampTime;
32cc592ed1SAxel Dörfler 	// Time value used for stamping each message header. Incremented by 1 second
33cc592ed1SAxel Dörfler 	// for each message, starts out with the current local time.
34667176abSJonas Sundström 
35667176abSJonas Sundström 
36cc592ed1SAxel Dörfler /*!	Global utility function to display an error message and return.  The message
37cc592ed1SAxel Dörfler 	part describes the error, and if errorNumber is non-zero, gets the string
38cc592ed1SAxel Dörfler 	", error code $X (standard description)." appended to it.  If the message
39cc592ed1SAxel Dörfler 	is NULL then it gets defaulted to "Something went wrong".
40667176abSJonas Sundström */
41cc592ed1SAxel Dörfler static void
DisplayErrorMessage(const char * messageString=NULL,status_t errorNumber=0,const char * titleString=NULL)42cc592ed1SAxel Dörfler DisplayErrorMessage(const char* messageString = NULL, status_t errorNumber = 0,
43cc592ed1SAxel Dörfler 	const char* titleString = NULL)
44667176abSJonas Sundström {
45cc592ed1SAxel Dörfler 	char errorBuffer[2048];
46667176abSJonas Sundström 
47cc592ed1SAxel Dörfler 	if (titleString == NULL)
48cc592ed1SAxel Dörfler 		titleString = "Error Message:";
49667176abSJonas Sundström 
50cc592ed1SAxel Dörfler 	if (messageString == NULL) {
51cc592ed1SAxel Dörfler 		if (errorNumber == B_OK)
52cc592ed1SAxel Dörfler 			messageString = "No error, no message, why bother?";
53667176abSJonas Sundström 		else
54cc592ed1SAxel Dörfler 			messageString = "Error";
55667176abSJonas Sundström 	}
56667176abSJonas Sundström 
57cc592ed1SAxel Dörfler 	if (errorNumber != 0) {
58*66fa08aaSMurai Takashi 		snprintf(errorBuffer, sizeof(errorBuffer), "%s: %s (%" B_PRIx32 ")"
59cc592ed1SAxel Dörfler 			"has occured.", messageString, strerror(errorNumber), errorNumber);
6032ebacf2SAxel Dörfler 		messageString = errorBuffer;
61667176abSJonas Sundström 	}
62667176abSJonas Sundström 
63cc592ed1SAxel Dörfler 	fputs(titleString, stderr);
64667176abSJonas Sundström 	fputc('\n', stderr);
65cc592ed1SAxel Dörfler 	fputs(messageString, stderr);
66667176abSJonas Sundström 	fputc('\n', stderr);
67667176abSJonas Sundström }
68667176abSJonas Sundström 
69667176abSJonas Sundström 
70cc592ed1SAxel Dörfler /*!	Determine if a line of text is the start of another message.  Pine mailbox
71cc592ed1SAxel Dörfler 	files have messages that start with a line that could say something like
72cc592ed1SAxel Dörfler 	"From agmsmith@achilles.net Fri Oct 31 21:19:36 EST 1997" or maybe something
73cc592ed1SAxel Dörfler 	like "From POPmail Mon Oct 20 21:12:36 1997" or in a more modern format,
74cc592ed1SAxel Dörfler 	"From agmsmith@achilles.net Tue Sep 4 09:04:11 2001 -0400".  I generalise it
75cc592ed1SAxel Dörfler 	to "From blah Day MMM NN XX:XX:XX TZONE1 YYYY TZONE2".  Blah is an e-mail
76cc592ed1SAxel Dörfler 	address you can ignore (just treat it as a word separated by spaces).  Day
77cc592ed1SAxel Dörfler 	is a 3 letter day of the week.  MMM is a 3 letter month name.  NN is the two
78cc592ed1SAxel Dörfler 	digit day of the week, has a leading space if the day is less than 10.
79cc592ed1SAxel Dörfler 	XX:XX:XX is the time, the X's are digits.  TZONE1 is the old style optional
80cc592ed1SAxel Dörfler 	time zone of 3 capital letters.  YYYY is the four digit year.  TZONE2 is the
81cc592ed1SAxel Dörfler 	optional modern time zone info, a plus or minus sign and 4 digits.  Returns
82cc592ed1SAxel Dörfler 	true if the line of text (ended with a NUL byte, no line feed or carriage
83cc592ed1SAxel Dörfler 	returns at the end) is the start of a message.
84667176abSJonas Sundström */
85cc592ed1SAxel Dörfler bool
IsStartOfMailMessage(char * lineString)86cc592ed1SAxel Dörfler IsStartOfMailMessage(char* lineString)
87667176abSJonas Sundström {
88cc592ed1SAxel Dörfler 	// It starts with "From "
8932ebacf2SAxel Dörfler 	if (memcmp("From ", lineString, 5) != 0)
90667176abSJonas Sundström 		return false;
91667176abSJonas Sundström 
92cc592ed1SAxel Dörfler 	char* string = lineString + 4;
93cc592ed1SAxel Dörfler 	while (*string == ' ')
94cc592ed1SAxel Dörfler 		string++;
95667176abSJonas Sundström 
96cc592ed1SAxel Dörfler 	// Skip over the e-mail address (or stop at the end of string).
97667176abSJonas Sundström 
98cc592ed1SAxel Dörfler 	while (*string != ' ' && *string != 0)
99cc592ed1SAxel Dörfler 		string++;
100cc592ed1SAxel Dörfler 	while (*string == ' ')
101cc592ed1SAxel Dörfler 		string++;
102667176abSJonas Sundström 
103cc592ed1SAxel Dörfler 	// TODO: improve this!!!
104cc592ed1SAxel Dörfler 
105cc592ed1SAxel Dörfler 	// Look for the 3 letter day of the week.
106cc592ed1SAxel Dörfler 	if (memcmp(string, "Mon", 3) != 0 && memcmp(string, "Tue", 3) != 0
107cc592ed1SAxel Dörfler 		&& memcmp(string, "Wed", 3) != 0 && memcmp(string, "Thu", 3) != 0
108cc592ed1SAxel Dörfler 		&& memcmp(string, "Fri", 3) != 0 && memcmp(string, "Sat", 3) != 0
109cc592ed1SAxel Dörfler 		&& memcmp(string, "Sun", 3) != 0) {
110cc592ed1SAxel Dörfler 		fprintf(stderr, "False alarm, not a valid day of the week in \"%s\""
111cc592ed1SAxel Dörfler 			".\n", lineString);
112667176abSJonas Sundström 		return false;
113667176abSJonas Sundström 	}
114667176abSJonas Sundström 
115cc592ed1SAxel Dörfler 	string += 3;
116cc592ed1SAxel Dörfler 	while (*string == ' ')
117cc592ed1SAxel Dörfler 		string++;
118667176abSJonas Sundström 
119cc592ed1SAxel Dörfler 	// Look for the 3 letter month code.
120cc592ed1SAxel Dörfler 	if (memcmp(string, "Jan", 3) != 0 && memcmp(string, "Feb", 3) != 0
121cc592ed1SAxel Dörfler 		&& memcmp(string, "Mar", 3) != 0 && memcmp(string, "Apr", 3) != 0
122cc592ed1SAxel Dörfler 		&& memcmp(string, "May", 3) != 0 && memcmp(string, "Jun", 3) != 0
123cc592ed1SAxel Dörfler 		&& memcmp(string, "Jul", 3) != 0 && memcmp(string, "Aug", 3) != 0
124cc592ed1SAxel Dörfler 		&& memcmp(string, "Sep", 3) != 0 && memcmp(string, "Oct", 3) != 0
125cc592ed1SAxel Dörfler 		&& memcmp(string, "Nov", 3) != 0 && memcmp(string, "Dec", 3) != 0) {
126667176abSJonas Sundström 		fprintf(stderr, "False alarm, not a valid month name in \"%s\".\n",
127cc592ed1SAxel Dörfler 			lineString);
128667176abSJonas Sundström 		return false;
129667176abSJonas Sundström 	}
130667176abSJonas Sundström 
131cc592ed1SAxel Dörfler 	string += 3;
132cc592ed1SAxel Dörfler 	while (*string == ' ')
133cc592ed1SAxel Dörfler 		string++;
134667176abSJonas Sundström 
135cc592ed1SAxel Dörfler 	// Skip the day of the month.  Require at least one digit.
136cc592ed1SAxel Dörfler 	if (*string < '0' || *string > '9') {
137667176abSJonas Sundström 		fprintf(stderr, "False alarm, not a valid day of the "
138cc592ed1SAxel Dörfler 			"month number in \"%s\".\n", lineString);
139667176abSJonas Sundström 		return false;
140667176abSJonas Sundström 	}
141667176abSJonas Sundström 
142cc592ed1SAxel Dörfler 	while (*string >= '0' && *string <= '9')
143cc592ed1SAxel Dörfler 		string++;
144cc592ed1SAxel Dörfler 	while (*string == ' ')
145cc592ed1SAxel Dörfler 		string++;
146667176abSJonas Sundström 
147cc592ed1SAxel Dörfler 	// Check the time.  Look for the sequence
148cc592ed1SAxel Dörfler 	// digit-digit-colon-digit-digit-colon-digit-digit.
149cc592ed1SAxel Dörfler 
150cc592ed1SAxel Dörfler 	if (string[0] < '0' || string[0] > '9'
151cc592ed1SAxel Dörfler 		|| string[1] < '0' || string[1] > '9'
152cc592ed1SAxel Dörfler 		|| string[2] != ':'
153cc592ed1SAxel Dörfler 		|| string[3] < '0' || string[3] > '9'
154cc592ed1SAxel Dörfler 		|| string[4] < '0' || string[4] > '9'
155cc592ed1SAxel Dörfler 		|| string[5] != ':'
156cc592ed1SAxel Dörfler 		|| string[6] < '0' || string[6] > '9'
157cc592ed1SAxel Dörfler 		|| string[7] < '0' || string[7] > '9') {
158667176abSJonas Sundström 		fprintf(stderr, "False alarm, not a valid time value in \"%s\".\n",
159cc592ed1SAxel Dörfler 			lineString);
160667176abSJonas Sundström 		return false;
161667176abSJonas Sundström 	}
162667176abSJonas Sundström 
163cc592ed1SAxel Dörfler 	string += 8;
164cc592ed1SAxel Dörfler 	while (*string == ' ')
165cc592ed1SAxel Dörfler 		string++;
166667176abSJonas Sundström 
167cc592ed1SAxel Dörfler 	// Look for the optional antique 3 capital letter time zone and skip it.
168cc592ed1SAxel Dörfler 	if (string[0] >= 'A' && string[0] <= 'Z'
169cc592ed1SAxel Dörfler 		&& string[1] >= 'A' && string[1] <= 'Z'
170cc592ed1SAxel Dörfler 		&& string[2] >= 'A' && string[2] <= 'Z') {
171cc592ed1SAxel Dörfler 		string += 3;
172cc592ed1SAxel Dörfler 		while (*string == ' ')
173cc592ed1SAxel Dörfler 			string++;
174667176abSJonas Sundström 	}
175667176abSJonas Sundström 
176cc592ed1SAxel Dörfler 	// Look for the 4 digit year.
177cc592ed1SAxel Dörfler 	if (string[0] < '0' || string[0] > '9'
178cc592ed1SAxel Dörfler 		|| string[1] < '0' || string[1] > '9'
179cc592ed1SAxel Dörfler 		|| string[2] < '0' || string[2] > '9'
180cc592ed1SAxel Dörfler 		|| string[3] < '0' || string[3] > '9') {
181667176abSJonas Sundström 		fprintf(stderr, "False alarm, not a valid 4 digit year in \"%s\".\n",
182cc592ed1SAxel Dörfler 			lineString);
183667176abSJonas Sundström 		return false;
184667176abSJonas Sundström 	}
185667176abSJonas Sundström 
186cc592ed1SAxel Dörfler 	string += 4;
187cc592ed1SAxel Dörfler 	while (*string == ' ')
188cc592ed1SAxel Dörfler 		string++;
189667176abSJonas Sundström 
190cc592ed1SAxel Dörfler 	// Look for the optional modern time zone and skip over it if present.
191cc592ed1SAxel Dörfler 	if ((string[0] == '+' || string[0] == '-')
192cc592ed1SAxel Dörfler 		&& string[1] >= '0' && string[1] <= '9'
193cc592ed1SAxel Dörfler 		&& string[2] >= '0' && string[2] <= '9'
194cc592ed1SAxel Dörfler 		&& string[3] >= '0' && string[3] <= '9'
195cc592ed1SAxel Dörfler 		&& string[4] >= '0' && string[4] <= '9') {
196cc592ed1SAxel Dörfler 		string += 5;
197cc592ed1SAxel Dörfler 		while (*string == ' ')
198cc592ed1SAxel Dörfler 			string++;
199667176abSJonas Sundström 	}
200667176abSJonas Sundström 
201cc592ed1SAxel Dörfler 	// Look for end of string.
202cc592ed1SAxel Dörfler 	if (*string != 0) {
203667176abSJonas Sundström 		fprintf(stderr, "False alarm, extra stuff after the "
204cc592ed1SAxel Dörfler 			"year/time zone in \"%s\".\n", lineString);
205667176abSJonas Sundström 		return false;
206667176abSJonas Sundström 	}
207667176abSJonas Sundström 
208667176abSJonas Sundström 	return true;
209667176abSJonas Sundström }
210667176abSJonas Sundström 
211667176abSJonas Sundström 
212cc592ed1SAxel Dörfler /*!	Read the input file, convert it to mbox format, and write it to standard
213cc592ed1SAxel Dörfler 	output.  Returns zero if successful, a negative error code if an error
214cc592ed1SAxel Dörfler 	occured.
215667176abSJonas Sundström */
216cc592ed1SAxel Dörfler status_t
ProcessMessageFile(char * fileName)217cc592ed1SAxel Dörfler ProcessMessageFile(char* fileName)
218667176abSJonas Sundström {
219cc592ed1SAxel Dörfler 	fprintf(stdout, "Now processing: \"%s\"\n", fileName);
220667176abSJonas Sundström 
221cc592ed1SAxel Dörfler 	FILE* inputFile = fopen(fileName, "rb");
222cc592ed1SAxel Dörfler 	if (inputFile == NULL) {
223cc592ed1SAxel Dörfler 		DisplayErrorMessage("Unable to open file", errno);
224cc592ed1SAxel Dörfler 		return errno;
225667176abSJonas Sundström 	}
226667176abSJonas Sundström 
227cc592ed1SAxel Dörfler 	// Extract a text message from the Mail file.
228667176abSJonas Sundström 
229cc592ed1SAxel Dörfler 	BString messageText;
230cc592ed1SAxel Dörfler 	int lineNumber = 0;
231667176abSJonas Sundström 
232cc592ed1SAxel Dörfler 	while (!feof(inputFile)) {
233cc592ed1SAxel Dörfler 		// First read in one line of text.
234cc592ed1SAxel Dörfler 		char line[102400];
235cc592ed1SAxel Dörfler 		if (fgets(line, sizeof(line), inputFile) == NULL) {
236cc592ed1SAxel Dörfler 			if (ferror(inputFile)) {
237cc592ed1SAxel Dörfler 				char errorString[2048];
238cc592ed1SAxel Dörfler 				snprintf(errorString, sizeof(errorString),
239cc592ed1SAxel Dörfler 					"Error while reading from \"%s\"", fileName);
240cc592ed1SAxel Dörfler 				DisplayErrorMessage(errorString, errno);
24132ebacf2SAxel Dörfler 				fclose(inputFile);
24232ebacf2SAxel Dörfler 				return errno;
243667176abSJonas Sundström 			}
244cc592ed1SAxel Dörfler 			break;
245cc592ed1SAxel Dörfler 				// No error, just end of file.
246667176abSJonas Sundström 		}
247667176abSJonas Sundström 
248cc592ed1SAxel Dörfler 		// Remove any trailing control characters (line feed usually, or CRLF).
249cc592ed1SAxel Dörfler 		// Might also nuke trailing tabs too. Doesn't usually matter. The main
250cc592ed1SAxel Dörfler 		// thing is to allow input files with both LF and CRLF endings (and
251cc592ed1SAxel Dörfler 		// even CR endings if you come from the Macintosh world).
252667176abSJonas Sundström 
253cc592ed1SAxel Dörfler 		char* string = line + strlen(line) - 1;
254cc592ed1SAxel Dörfler 		while (string >= line && *string < 32)
255cc592ed1SAxel Dörfler 			string--;
256cc592ed1SAxel Dörfler 		*(++string) = 0;
257667176abSJonas Sundström 
258cc592ed1SAxel Dörfler 		if (lineNumber == 0 && line[0] == 0) {
259cc592ed1SAxel Dörfler 			// Skip leading blank lines.
260cc592ed1SAxel Dörfler 			continue;
261cc592ed1SAxel Dörfler 		}
262cc592ed1SAxel Dörfler 		lineNumber++;
263667176abSJonas Sundström 
264cc592ed1SAxel Dörfler 		// Prepend the new mbox message header, if the first line of the message
265cc592ed1SAxel Dörfler 		// doesn't already have one.
266cc592ed1SAxel Dörfler 		if (lineNumber == 1 && !IsStartOfMailMessage(line)) {
267cc592ed1SAxel Dörfler 			time_t timestamp = gDateStampTime++;
268cc592ed1SAxel Dörfler 			messageText.Append("From baron@be.com ");
269cc592ed1SAxel Dörfler 			messageText.Append(ctime(&timestamp));
270667176abSJonas Sundström 		}
271667176abSJonas Sundström 
272cc592ed1SAxel Dörfler 		// Append the line to the current message text.
273cc592ed1SAxel Dörfler 		messageText.Append(line);
274cc592ed1SAxel Dörfler 		messageText.Append("\n");
275667176abSJonas Sundström 	}
276667176abSJonas Sundström 
277cc592ed1SAxel Dörfler 	// Remove blank lines from the end of the message (a pet peeve of mine), but
278cc592ed1SAxel Dörfler 	// end the message with two new lines to separate it from the next message.
279cc592ed1SAxel Dörfler 	int i = messageText.Length();
280cc592ed1SAxel Dörfler 	while (i > 0 && (messageText[i - 1] == '\n' || messageText[i - 1] == '\r'))
281667176abSJonas Sundström 		i--;
282cc592ed1SAxel Dörfler 	messageText.Truncate(i);
283cc592ed1SAxel Dörfler 	messageText.Append("\n\n");
284667176abSJonas Sundström 
285cc592ed1SAxel Dörfler 	// Write the message out.
28632ebacf2SAxel Dörfler 
28732ebacf2SAxel Dörfler 	status_t status = B_OK;
28832ebacf2SAxel Dörfler 
289cc592ed1SAxel Dörfler 	if (puts(messageText.String()) < 0) {
290cc592ed1SAxel Dörfler 		DisplayErrorMessage ("Error while writing the message", errno);
291cc592ed1SAxel Dörfler 		status = errno;
29232ebacf2SAxel Dörfler 	}
293667176abSJonas Sundström 
294cc592ed1SAxel Dörfler 	fclose(inputFile);
295cc592ed1SAxel Dörfler 	return status;
296667176abSJonas Sundström }
297667176abSJonas Sundström 
298667176abSJonas Sundström 
299cc592ed1SAxel Dörfler int
main(int argc,char ** argv)300cc592ed1SAxel Dörfler main(int argc, char** argv)
301667176abSJonas Sundström {
302cc592ed1SAxel Dörfler 	BApplication app("application/x-vnd.Haiku-mail2mbox");
303667176abSJonas Sundström 
304cc592ed1SAxel Dörfler 	if (argc <= 1 || argc >= 3) {
3059563f44bSStephan Aßmus 		printf("%s is a utility for converting Mail e-mail\n", argv[0]);
306667176abSJonas Sundström 		printf("files to Unix Pine style e-mail files.  It could well\n");
307667176abSJonas Sundström 		printf("work with other Unix style mailbox files.  Each message in\n");
308667176abSJonas Sundström 		printf("the input directory is converted and sent to the standard\n");
309667176abSJonas Sundström 		printf("output.  Usage:\n\n");
31008c63a2dSAxel Dörfler 		printf("%s InputDirectory >OutputFile\n\n", kProgramName);
311667176abSJonas Sundström 		printf("Public domain, by Alexander G. M. Smith.\n");
312667176abSJonas Sundström 		return -10;
313667176abSJonas Sundström 	}
314667176abSJonas Sundström 
315cc592ed1SAxel Dörfler 	// Set the date stamp to the current time.
316cc592ed1SAxel Dörfler 	gDateStampTime = time (NULL);
317667176abSJonas Sundström 
318cc592ed1SAxel Dörfler 	// Try to open the input directory.
319cc592ed1SAxel Dörfler 	char inputPathName[B_PATH_NAME_LENGTH];
320cc592ed1SAxel Dörfler 	strlcpy(inputPathName, argv[1], sizeof(inputPathName) - 2);
321667176abSJonas Sundström 
322cc592ed1SAxel Dörfler 	char tempString[2048];
323667176abSJonas Sundström 
324cc592ed1SAxel Dörfler 	DIR* dir = opendir(inputPathName);
325cc592ed1SAxel Dörfler 	if (dir == NULL) {
326cc592ed1SAxel Dörfler 		sprintf(tempString, "Problems opening directory named \"%s\".",
327cc592ed1SAxel Dörfler 			inputPathName);
328cc592ed1SAxel Dörfler 		DisplayErrorMessage(tempString, errno);
329cc592ed1SAxel Dörfler 		return 1;
330667176abSJonas Sundström 	}
331667176abSJonas Sundström 
332cc592ed1SAxel Dörfler 	// Append a trailing slash to the directory name, if it needs one.
33332ebacf2SAxel Dörfler 	if (inputPathName[strlen(inputPathName) - 1] != '/')
334cc592ed1SAxel Dörfler 		strcat(inputPathName, "/");
335667176abSJonas Sundström 
336cc592ed1SAxel Dörfler 	int messagesDoneCount = 0;
337cc592ed1SAxel Dörfler 	status_t status = B_OK;
338667176abSJonas Sundström 
339cc592ed1SAxel Dörfler 	while (dirent_t* entry = readdir(dir)) {
340cc592ed1SAxel Dörfler 		// skip '.' and '..'
341cc592ed1SAxel Dörfler 		if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
342667176abSJonas Sundström 			break;
343667176abSJonas Sundström 
344cc592ed1SAxel Dörfler 		strlcpy(tempString, inputPathName, sizeof(tempString));
34532ebacf2SAxel Dörfler 		strlcat(tempString, entry->d_name, sizeof(tempString));
346cc592ed1SAxel Dörfler 
347cc592ed1SAxel Dörfler 		status = ProcessMessageFile(tempString);
348cc592ed1SAxel Dörfler 		if (status != B_OK)
349cc592ed1SAxel Dörfler 			break;
350cc592ed1SAxel Dörfler 
351cc592ed1SAxel Dörfler 		messagesDoneCount++;
352667176abSJonas Sundström 	}
353cc592ed1SAxel Dörfler 
354cc592ed1SAxel Dörfler 	closedir(dir);
355cc592ed1SAxel Dörfler 
356cc592ed1SAxel Dörfler 	if (status != B_OK) {
357cc592ed1SAxel Dörfler 		DisplayErrorMessage("Stopping early because an error occured", status);
35832ebacf2SAxel Dörfler 		return status;
359667176abSJonas Sundström 	}
360667176abSJonas Sundström 
361cc592ed1SAxel Dörfler 	fprintf(stderr, "Did %d messages successfully.\n", messagesDoneCount);
362667176abSJonas Sundström 	return 0;
363667176abSJonas Sundström }
364